How to print content of $2 after "\" - bash

I have a script named "test.sh"
#!/bin/bash
echo "sed -i '/$1/c\$2' $3"
Running as: ./test.sh "This line is removed." "some text here" out.txt . I want this to be printed exactly:
sed -i '/This line is removed./c\some text here' out.txt
Output is printing as:
sed -i '/This line is removed./c$2' out.txt
The problem is there with \$ it is printing $ not allowing content of $2. How to do this?

Use this line in your script with double slash:
#!/bin/bash
echo "sed -i '/$1/c\\$2' $3"

try this
echo "sed -i '/$1/c\\$2' $3"

Related

Sed find and replace expression works with literal but not with variable interpolation

For the following MVCE:
echo "test_num: 0" > test.txt
test_num=$(grep 'test_num:' test.txt | cut -d ':' -f 2)
new_test_num=$((test_num + 1))
echo $test_num
echo $new_test_num
sed -i "s/test_num: $test_num/test_num: $new_test_num/g" test.txt
cat test.txt
echo "sed -i "s/test_num: $test_num/test_num: $new_test_num/g" test.txt"
sed -i "s/test_num: 0/test_num: 1/g" test.txt
cat test.txt
Which outputs
0 # parsed original number correctly
1 # increment the number
test_num: 0 # sed with interpolated variable, does not work
sed -i s/test_num: 0/test_num: 1/g test.txt # interpolated parameter looks right
test_num: 1 # ???
Why does sed -i "s/test_num: $test_num/test_num: $new_test_num/g" test.txt not produce the expected result when sed -i "s/test_num: 0/test_num: 1/g" test.txt works just fine in the above example?
As mentioned in the comment, there is a white space in ${test_num}. Therefore in your sed there should not be an empty space between the colon and your variable.
Also I guess you should surround your variable with curly bracket {} to increase readability.
sed "s/test_num:${test_num}/test_num: ${new_test_num}/g" test.txt
test_num: 1
If you just want the number in ${test_num}, you can try something like:
grep 'test_num:' test.txt | awk -F ': ' '{print $2}'
awk allows to specify delimiter with more than 1 character.
Instead of grep|cut you can also use sed.
#! /bin/bash
exec <<EOF
test_num: 0
EOF
grep 'test_num:' | cut -d ':' -f 2
exec <<EOF
test_num: 0
EOF
sed -n 's/^test_num: //p'
When using regexp replace in sed there is special meaning to $ .
Suggesting to rebuild your sed command segments as follow:
sed -i 's/test_num: '$test_num'/test_num: '$new_test_num'/g' test.txt
Other option, use echo command to expand variables in sed command.
sed_command=$(echo "s/test_num:${test_num}/test_num: ${new_test_num}/g")
sed -i "$sed_command" test.txt

Passing variables between sed script and bash script

I have a shell script with up to 5 parameters. There is files with placeholders. I would like to use sed script file depending of the one variable. The problem is that when I have variables defined in the sed script - values of those variables are not put in placeholders.
#!/bin/bash
A=$1
B=$2
echo "Some string with _PH1_ place holders _PH2_"|sed -i -f script1.sed >> file.txt
one of the sed scripts file
#Sed script 1
s/_PH1_/${A}/g
s/_PH2_/${B}/g
If your sed script is that short, you might as well inline it in bash:
#!/bin/bash
A=$1
B=$2
#your sed commands but still part of the bash script:
sed -i -e "s/_PH1_/${A}/g" file.txt
sed -i -e "/_PH2_/${B}/g" file.txt
You need to create the sed script as part of your bash script so the variable substitution takes place:
#!/bin/bash
A=$1
B=$2
cat >> script1.sed << EOF
s/_PH1_/${A}/g
s/_PH2_/${B}/g
EOF
echo "Some string with _PH1_ place holders _PH2_"|sed -i -f script1.sed >> file.txt
$ cat tst.sh
#!/bin/bash
set -a
A="$1"
B="$2"
sedScript=$(mktemp)
printf 'sed "\n' >> "$sedScript"
cat script1.sed >> "$sedScript"
printf '"\n' >> "$sedScript"
echo "Some string with _PH1_ place holders _PH2_" | "$sedScript"
rm -f "$sedScript"
$ ./tst.sh foo bar
Some string with foo place holders bar

Unable to output values in the required format using shell script

I need to output an array to a file in the following format.
File: a.txt
b.txt
I tried doing the following :
declare -a files=("a.txt" "b.txt")
empty=""
printf "File:" >> files.txt
for i in "${files[#]}"
do
printf "%-7s %-30s \n" "$empty" "$i" >> files.txt
done
But, I get the output as
File: a.txt
b.txt
Can anyone please help me to get the output in the required format.
#!/bin/bash
files=( 'a.txt' 'b.txt' 'c.txt' 'd.txt' )
set -- "${files[#]}"
printf 'File: %s\n' "$1"
shift
printf ' %s\n' "$#"
Output:
File: a.txt
b.txt
c.txt
d.txt
This uses the fact that printf will reuse its formatting string for all its other command line parameters.
We set the positional parameters to the list and then output the first element with the File: string prepended. We then shift $1 off the list of positional parameters and print the rest with a spacer string inserted.
Using sed
#!/bin/bash
declare -a files=("a.txt" "b.txt")
for i in "${files[#]}"
do
echo "$i" >> files.txt
done
sed -i '1 s/^/File: /' files.txt
sed -i '1 ! s/^/ /' files.txt
If you are using Mac, you have to modify sed commands in this way
sed -i '' '1 s/^/File: /' files.txt
sed -i '' '1 ! s/^/ /' files.txt
The output will be:
File: a.txt
b.txt
First of all we put into txt file all the file names (for loop). After that, via first sed command we add File: to the first line and via second sed command we add to all lines, except the first, six spaces equal to length of string File:
You could always started with a variable containing File: for the first iteration, and overwrite it with the correct number of spaces each time. The repeated assignment won't induce too much overhead.
prefix="File:"
for i in "${files[#]}"
do
printf "%-7s %-30s \n" "$prefix" "$i"
prefix=
done > Files.txt

Text replacement bash script

I want to replace a' into à, e' into è, etc. into a file with a script like this:
#!/bin/sh
if [ -e "$1" ]
then
sed 's/a'/\à/g' -i "$1";
sed 's/e'/\è/g' -i "$1";
sed 's/i'/\ì/g' -i "$1";
sed 's/o'/\ò/g' -i "$1";
sed 's/u'/\ù/g' -i "$1";
else
echo "File not found!"
fi
But I get this error:
Syntax error: Unterminated quoted string
I don't know how to wrote '
Yes there is syntax problem, try your sed command as this:
sed -i "s/a'/à/g" "$1"
sed -i "s/e'/è/g" "$1"
sed -i "s/i'/ì/g" "$1"
sed -i "s/o'/ò/g" "$1"
sed -i "s/u'/ù/g" "$1"
Problem was that you were using nested single quote (quote inside code).
Exit the single quotes, then put an escaped quote, then start another single quoted string:
sed 's/a'\''/\à/g' -i "$1"
awk '{ gsub(/e'\''/,"è"); print}' "$1"
Yet another solution available in bash is $'...' quoting, which does allow escaped single quotes:
sed $'s/a\'/\à/g' -i "$1";

Concatenate grep output string (bash script)

I'm processing some data from a text file using a bash script (Ubuntu 12.10).
The basic idea is that I select a certain line from a file using grep. Next, I process the line to get the number with sed. Both the grep and sed command are working. I can echo the number.
But the concatenation of the result with a string goes wrong.
I get different results when combining string when I do a grep command from a variable or a file. The concatenation goes wrong when I grep a file. It works as expected when I grep a variable with the same text as in the file.
What am I doing wrong with the grep from a file?
Contents of test.pdb
REMARK overall = 324.88
REMARK bon = 24.1918
REMARK coup = 0
My script
#!/bin/bash
#Correct function
echo "Working code"
TEXT="REMARK overall = 324.88\nREMARK bon = 24.1918\nREMARK coup = 0\n"
DATA=$(echo -e $TEXT | grep 'overall' | sed -n -e "s/^.*= //p" )
echo "Data: $DATA"
DATA="$DATA;0"
echo $DATA
#Not working
echo ""
echo "Not working code"
DATA=$(grep 'overall' test.pdb | sed -n -e "s/^.*= //p")
echo "Data: $DATA"
DATA="$DATA;0"
echo $DATA
Output
Working code
Data: 324.88
324.88;0
Not working code
Data: 324.88
;04.88
I went crazy with the same issue.
The real problem is that your "test.pdb" has probably a wrong EOL (end of line) character.
Linux EOL: LF (aka \n)
Windows EOL: CR LF (aka \r \n)
This mean that echo and grep will have problem with this extra character (\r), luckily tr, sed and awk manage it correctly.
So you can try also with:
DATA=$(grep 'overall' test.pdb | sed -n -e "s/^.*= //p" | sed -e 2s/\r$//")
or
DATA=$(grep 'overall' test.pdb | sed -n -e "s/^.*= //p" | tr -d '\r')
With awk, it will be more reliable and cleaner I guess :
$ awk '$2=="overall"{print "Working code\nData: " $4 "\n" $4 ";0"}' file.txt
Working code
Data: 324.88
324.88;0
Try this:
SUFFIX=";0"
DATA="${DATA}${SUFFIX}"

Resources