sed command results in unterminated address regex - bash

I'm trying to search and replace a string with the sed command in linux but keep getting errors in STDERR such as
sed: -e expression #1, char 53: unterminated address regex
Here's what doing:
string="SOMEFILE.TXT SOMEFILE2.TXT SOMEFILE3.TXT"
path="/path/to/file/"
replace="TXT \] || \[ ${path}SOME"
formatted_string=`echo ${string} | sed -e "/TXT SOME/${replace}/g"`
if [ -e ${path}/${formatted_string} ]; then
The end goal is to have a formatted string to insert into the if command to look for one or more files if they exist. The string with files can vary so that's why I'm doing this. The above code works and it does find the files but I can't get rid of the error.
Thanks for any help

The right way
array=( "SOMEFILE.TXT" "SOMEFILE2.TXT" "SOMEFILE3.TXT")
path_to_file="/path/to/file/"
file_exist=
for filename in "#{array[#]}"; do
if [ -e "${path_to_file}/${filename}" ]; then
file_exist=1
fi
done
if [ -n "${file_exist:+X}" ]; then
...
or shorter (one-liner)
shopt -s extglob
if [ -e "/file/to/path/"#("SOMEFILE.TXT"|"SOMEFILE2.TXT"|"SOMEFILE3.TXT") ]; then

Can you try this code
string="SOMEFILE.TXT SOMEFILE2.TXT SOMEFILE3.TXT"
path="\/path\/to\/file\/"
replace="TXT \] || \[ ${path}SOME"
formatted_string=`echo ${string} | sed -e "s/TXT SOME/${replace}/g"`
echo $formatted_string

It sounds like all you need is something like:
if ls /path/to/file/SOMEFILE*.TXT >/dev/null 2>&1; then
at least one file exists so do whatever...
fi
or if you want to do something with the list of files:
shopt -s nullglob
files=(/path/to/file/SOMEFILE*.TXT)
if [ ${#files[#]} -gt 0 ]; then
at least one file exists so do whatever...
fi

Thanks for all the help! I ended up omitting the sed command altogether and found a more practical solution:
string="/path/to/file/SOMEFILE*.TXT"
files=$(ls ${string} 2> /dev/null | wc -l)
if [ **"$files" != "0"** ]; then
This does what I need and seems easier to read than what I was trying to do earlier.

Related

Get char before Substring in bash

i try to get the char before a substring in bash.
Some examples of the String:
label="LLL:EXT:xxx/Resources/Private/Language/locallang.xlf:flux.content"
or:
label='LLL:EXT:xxx/Resources/Private/Language/locallang.xlf:flux.content'
or:
$this->getLanguageService()->sL('LLL:EXT:xxx/Resources/Private/Language/locallang.xlf:flux.content'
i need to know if there is a single- or doublequote before the LLL. :)
You can get the character using pure Bash code with:
[[ $string =~ (.)LLL ]] && char=${BASH_REMATCH[1]}
See the sections on [[...]] and BASH_REMATCH in the Bash Reference Manual.
You are asking whether or not there is a ' or " before LLL. The shortest answer would be grep -q "['\"]LLL".
If the exit code is 0, then the answer is yes, if the exit code is 1, then the answer is no.
For example:
$ echo 'label="LLL:EXT:xxx/Resources/Private/Language/locallang.xlf:flux.content"' | grep -q "['\"]LLL"
$ echo $?
0
$ echo test | grep -q "['\"]LLL"
$ echo $?
1
You can use grep for this.
grep -E -o '.{0,1}LLL' file
grep -E -o '.{0,1}LLL' file | cut -c-1 # shows only the first character
-E indicates the pattern is an extended regular expression
-o shows only the matching portion
'.{0,1}LLL' specifies the pattern with the first preceding character appended

bash : change part of filename to lowercase

I need to rename a list of files changing any file extension to lowercase:
ie: from My_TEST.ONE.two.Three.fOuR.FIve to My_TEST.one.two.three.four.five
At the moment the way I've found is this one
#!/bin/bash
sourcefilename="My_TEST.ONE.two.Three.fOuR.FIve"
newfilename=""
for word in $(echo $sourcefilename | tr '.' '\n'); do
if [ -z "$newfilename" ]; then
newfilename="$word"
else
newfilename="$newfilename.$(echo $word | tr [:upper:] [:lower:])"
fi
done
Is there a better (and maybe elegant) approach?
Use bash Parameter Expansion features.
fileName='My_TEST.ONE.two.Three.fOuR.FIve'
first="${fileName%%.*}"
rest="${fileName#*.}"
echo mv -v "${fileName}" "${first}.${rest,,[A-Z]}"

Missing "))" in shell script

I'm really sorry I'm a total noob in shell scripting, I looked on the Internet and I didn't find the answer
=> /home/bee/Scripts/chkbsh: 11: /home/bee/Scripts/chkbsh: Syntax error: Missing '))'
#!/bin/sh
for file in $((gawk '/^#!.*( |[/])sh/{printf "%s\0", FILENAME} {nextfile}' /usr/bin/* 2>/dev/null) | xargs -0); do
checkbashisms "$file" >/dev/null 2>&1
if [ "$?" -gt 0 ]
then
sed -i 's:^#!.*/bin/sh:#!/bin/bash:' "$file";
echo "$file" has been processed!
fi
done
echo ":3"
If I change #!/bin/sh in #!/bin/bash everything is okay
You have opening double parentheses, but two single closing parentheses. Place a space after the first (, like this:
for file in $( (gawk '/^#!.*( |[/])sh/{printf "%s\0", FILENAME}
^ there
BTW, it's always good advice to test your scripts with ShellCheck, this way you could have easily spotted above error.
Try
for file in `gawk '/^#!.*( |[/])sh/{printf "%s\0", FILENAME} {nextfile}' /usr/bin/* 2>/dev/null | xargs -0`; do
checkbashisms "$file" >/dev/null 2>&1

Substitution with sed + bash function

my question seems to be general, but i can't find any answers.
In sed command, how can you replace the substitution pattern by a value returned by a simple bash function.
For instance, I created the following function :
function parseDates(){
#Some process here with $1 (the pattern found)
return "dateParsed;
}
and the folowing sed command :
myCatFile=`sed -e "s/[0-3][0-9]\/[0-1][0-9]\/[0-9][0-9]/& parseDates &\}/p" myfile`
I found that the caracter '&' represents the current pattern found, i'd like it to be passed to my bash function and the whole pattern to be substituted by the pattern found +dateParsed.
Does anybody have an idea ?
Thanks
you can use the "e" option in sed command like this:
cat t.sh
myecho() {
echo ">>hello,$1<<"
}
export -f myecho
sed -e "s/.*/myecho &/e" <<END
ni
END
you can see the result without "e":
cat t.sh
myecho() {
echo ">>hello,$1<<"
}
export -f myecho
sed -e "s/.*/myecho &/" <<END
ni
END
Agree with Glenn Jackman.
If you want to use bash function in sed, something like this :
sed -rn 's/^([[:digit:].]+)/`date -d #&`/p' file |
while read -r line; do
eval echo "$line"
done
My file here begins with a unix timestamp (e.g. 1362407133.936).
Bash function inside sed (maybe for other purposes):
multi_stdin(){ #Makes function accepet variable or stdin (via pipe)
[[ -n "$1" ]] && echo "$*" || cat -
}
sans_accent(){
multi_stdin "$#" | sed '
y/àáâãäåèéêëìíîïòóôõöùúûü/aaaaaaeeeeiiiiooooouuuu/
y/ÀÁÂÃÄÅÈÉÊËÌÍÎÏÒÓÔÕÖÙÚÛÜ/AAAAAAEEEEIIIIOOOOOUUUU/
y/çÇñÑߢÐð£Øø§µÝý¥¹²³ªº/cCnNBcDdLOoSuYyY123ao/
'
}
eval $(echo "Rogério Madureira" | sed -n 's#.*#echo & | sans_accent#p')
or
eval $(echo "Rogério Madureira" | sed -n 's#.*#sans_accent &#p')
Rogerio
And if you need to keep the output into a variable:
VAR=$( eval $(echo "Rogério Madureira" | sed -n 's#.*#echo & | desacentua#p') )
echo "$VAR"
do it step by step. (also you could use an alternate delimiter , such as "|" instead of "/"
function parseDates(){
#Some process here with $1 (the pattern found)
return "dateParsed;
}
value=$(parseDates)
sed -n "s|[0-3][0-9]/[0-1][0-9]/[0-9][0-9]|& $value &|p" myfile
Note the use of double quotes instead of single quotes, so that $value can be interpolated
I'd like to know if there's a way to do this too. However, for this particular problem you don't need it. If you surround the different components of the date with ()s, you can back reference them with \1 \2 etc and reformat however you want.
For instance, let's reverse 03/04/1973:
echo 03/04/1973 | sed -e 's/\([0-9][0-9]\)\/\([0-9][0-9]\)\/\([0-9][0-9][0-9][0-9]\)/\3\/\2\/\1/g'
sed -e 's#[0-3][0-9]/[0-1][0-9]/[0-9][0-9]#& $(parseDates &)#' myfile |
while read -r line; do
eval echo "$line"
done
You can glue together a sed-command by ending a single-quoted section, and reopening it again.
sed -n 's|[0-3][0-9]/[0-1][0-9]/[0-9][0-9]|& '$(parseDates)' &|p' datefile
However, in contrast to other examples, a function in bash can't return strings, only put them out:
function parseDates(){
# Some process here with $1 (the pattern found)
echo dateParsed
}

How to search an expression in a file from a bash script?

I have a bash script.
I need to look if "text" exists in the file and do something if it exists.
If you need to execute a command on all files containing the text, you can combine grep with xargs. For example, this would remove all files containing "yourtext":
grep -l "yourtext" * | xargs rm
To search a single file, use if grep ...
if grep -q "yourtext" yourfile ; then
# Found
fi
Something like the following would do what you need.
grep -w "text" file > /dev/null
if [ $? -eq 0 ]; then
#Do something
else
#Do something else
fi
grep is your friend here
You can put the grep inside the if statement, and you can use the -q flag to silence it.
if grep -q "text" file; then
:
else
:
fi
cat <file> | grep <"text"> and check the return code with test $?
Check out the excellent:
Advanced Bash-Scripting Guide
just use the shell
while read -r line
do
case "$line" in
*text* )
echo "do something here"
;;
* ) echo "text not found"
esac
done <"file"

Resources