sed gives me ": unexpected EOF (pending }'s) error and I have no idea why - sed

I'm trying to port a GNU sed command to BSD sed (in OSX). The command is:
cat -- "$1" | sed -n -e "\${/^#/H;x;/${tapPrintTapOutputSedPattern}/p;}" \
-e "/${tapPrintTapOutputSedPattern}/{x;/${tapPrintTapOutputSedPattern}/p;b;}" \
-e "/^#/{H;b;}" \
-e "x;/${tapPrintTapOutputSedPattern}/p" \
-e "/^Bail out!/q"
It works on GNU sed, but BSD sed gives this error:
sed: 2: "/^Bail out!/q
": unexpected EOF (pending }'s)
This is the command after the variable expansions, in case it's relevant:
cat -- "test021.tap" | sed -n \
-e "\${/^#/H;x;/^not ok\|^ok \([0-9]\+ \)\?# [tT][oO][dD][oO]\|^Bail out!/p;}" \
-e "/^not ok\|^ok \([0-9]\+ \)\?# [tT][oO][dD][oO]\|^Bail out!/{x;/^not ok\|^ok \([0-9]\+ \)\?# [tT][oO][dD][oO]\|^Bail out!/p;b;}" \
-e "/^#/{H;b;}" \
-e "x;/^not ok\|^ok \([0-9]\+ \)\?# [tT][oO][dD][oO]\|^Bail out!/p" \
-e "/^Bail out!/q"
Any ideas about why/how to fix it?
Cheers!

Try using newlines instead of a semicolons, at least before the branch commands (b) in the statements. See if this works:
sed -n "
\${
/^#/H
x
/${tapPrintTapOutputSedPattern}/p
}
/${tapPrintTapOutputSedPattern}/{
x
/${tapPrintTapOutputSedPattern}/p
b
}
/^#/{
H
b
}
x
/${tapPrintTapOutputSedPattern}/p
/^Bail out!/q
" "$1"

Related

Sed to Replace & and slashes

I have a data in below format.
new_name='abc &eft / def \ mno'
1.json
{
"text": {
"attribute": "old_name",
"data": "xyz"
}
}
I am trying to replace the value old_name by new_name.
My trail :--
sed "s/old_name/${new_name/&/\&}; s/old_name/${new_name////\/}/g" 1.json
I get below error :--
sed: -e expression #1, char 67: unknown option to `s'
Any guidance would be of great help.
You can skip the need to escape the slash by using a different delimiter for the substitution, but you still need to do one of the other replacements outside the sed command:
new_name='abc &eft / def \ mno'
quoted=${new_name/\\/\\\\\\\\}
sed "s=old_name=${quoted//&/\\&}=g" 1.json
But jq is far better tool to handle json:
new_name='abc &eft / def \ mno'
jq --arg n "$new_name" \
'.text.attribute |= (if . == "old_name" then $n else . end)' 1.json

How to find a variable and replace it with other variable in Perl?

I have tried the below Perl command to find a $from_word variable and replace it with $to_word variable in the $bat_file_path file.
system("perl -i -p -e 's/$from_word/$to_word/ee' $bat_file_path");
but I get error as
Substitution replacement not terminated at -e line 4.
Also it did not replaced as expected.
Please help me out of this concern.
sub change_cg_name {
if(!-e $output_running) {
print ("show running file not available. test case failed. [$output_running]");
return 0;
}
if(!-e $bat_file_path) {
print ("bat file not available test case filed. [$bat_file_path]");
return 0
}
my $from_word=`grep 'config-group type node IMPT_' $bat_file_path | awk '{print \$(4)}'`;
my $to_word= `grep 'config-group type node IMPT_' $output_running | awk '{print \$(4)}'`;
print("from WORD IS [$from_word]");
print("TO WORD IS [$to_word]");
if($to_word ne "") {
if (index($to_word, "IMPT_") != -1) {
system("perl -i -p -e 's/"$from_word"/"$to_word"/ee' $bat_file_path");
system("perl -p -i -e 's/\r\n$/\n/g' $bat_file_path");
print("ARUL changed the impt name in the bat file [$to_word] and file [$bat_file_path]");
return 0;
}
}
}
Change this line:
system("perl -i -p -e 's/"$from_word"/"$to_word"/ee' $bat_file_path");
with
system("perl -i -p -e 's/$from_word/$to_word/ee' $bat_file_path");
serenesat is right in removing the incorrectly nested quotation marks.
glenn jackman is right in pointing to the line endings in the $from_word and $to_word values. Instead of removing them, I suggest not to produce them in the first place by changing the awk command print \$(4) to printf "%s", \$(4).
Finally, in the command system("perl -p -i -e 's/\r\n$/\n/g' $bat_file_path") the \n and $ need \-escaping: system("perl -p -i -e 's/\r\\n\$/\\n/g' $bat_file_path").

Colorize running log after marker

Often I need to analyze large logs in console.
I use the following command to colorize important keywords:
echo "string1\nerror\nsuccess\nstring2\nfail" | perl -p -e 's/(success)/\e[1;32;10m$&\e[0m/g;' -e 's/(error|fail)/\e[0;31;10m$&\e[0m/g'
It will colorize "success" with green, and error messages with red and keeps others lines unchanged (as they contain some useful info).
But in some cases I need to colorize values after some marker, but not marker itself, i.e. in these lines
Marker1: value1
Marker2: value2
need to highlight only value1 and value2 by known markers.
I'm looking for a way to modify my current oneliner to add this function
Also I tried the following solution, which I like less
#!/bin/bash
default=$(tput op)
red=$(tput setaf 1 || tput AF 1)
green=$(tput setaf 2 || tput AF 2)
sed -u -r "s/(Marker1: )(.+)$/\1${red}\2${default}/
s/(Marker2: )(.+)$/\1${green}\2${default}/" "${#}"`
But it has some problem with buffering, so it's ok for some constant file, but log which is continuosly running is not displayed at all
UPDATE:
Found a solution with help of some perl guru.
echo -e "string1\nerror\nsuccess\nstring2\nfail\nMaker1: value1\nMaker2: value2" | \
perl -p \
-e 's/(success)/\e[32m$&\e[0m/g;' \
-e 's/(error|fail)/\e[31m$&\e[0m/g;' \
-e 's/(Maker1:) (.*)/$1 \e[36m$2\e[0m/m;' \
-e 's/(Maker2:) (.*)/$1 \e[01;34m$2\e[0m/m;'
echo -e "string1\nerror\nsuccess\nstring2\nfail\nMaker1: value1\nMaker2: value2" | \
perl -p \
-e 's/(success)/\e[32m$&\e[0m/g;' \
-e 's/(error|fail)/\e[31m$&\e[0m/g;' \
-e 's/(Maker1:) (.*)/$1 \e[36m$2\e[0m/m;' \
-e 's/(Maker2:) (.*)/$1 \e[01;34m$2\e[0m/m;'
#!/bin/bash
default=$(tput op)
red=$(tput setaf 1 || tput AF 1)
green=$(tput setaf 2 || tput AF 2)
#default='e[0m'
#red='e[0;31;10m'
#green='e[1;32;10m'
# automaticaly use passed argument file if any or stdin if not
sed -u -r \
"/success/ s//${green}&${default}/
/error|fail/ s//${red}&${default}/
/^Marker1:/ {s//\1${red}/;s/$/${default}/;}
/^Marker2:/ {s//\1${green}/;s/$/${default}/;}" \
$( [ ${##} -gt 0 ] && echo ${#} )
For a one line:
remove other line thans sed one
replace newline in sed by ;
use directly the terminal code in place of variable
remove the last line if you pipe or use specific file instead

sed replace string except the matched string

Problem statement:
change every user agent that does not match A2PC or GENCOM with the user agent PROHIBITED and keep GENCOM and A2PC unchanged
Expression:
echo \"GENCOM\" | sed -r -e 's/(^((?!A2PC)(?!GENCOM).)*$)/PROHIBITED/g'
error:
sed: -e expression #1, char 41: Invalid preceding regular expression
I removed -r then error not thrown but its not working
echo \"GENDFGGH\" | sed -e 's/(^((?!A2PC)(?!GENCOM).)*$)/PROHIBITED/g'
"GENDFGGH"
Please help me for this solution
First look for your pattern and then do the sub:
# echo \"GENCsOM\" | sed -e '/^"\(GENCOM\|A2PC\)"$/! s/^.*$/PROHIBITED/'
PROHIBITED
# echo \"GENCOM\" | sed -e '/^"\(GENCOM\|A2PC\)"$/! s/^.*$/PROHIBITED/'
"GENCOM"
sed '/A2PC/ !{
/GENCOM/ ! {
s/$/PROHIBITED/
}
}' YourFile
double exclusion than a change, posix compliant

Unix - Removing everything after a pattern using sed

I have a file which looks like below:
memory=500G
brand=HP
color=black
battery=5 hours
For every line, I want to remove everything after = and also the =.
Eventually, I want to get something like:
memory:brand:color:battery:
(All on one line with colons after every word)
Is there a one-line sed command that I can use?
sed -e ':a;N;$!ba;s/=.\+\n\?/:/mg' /my/file
Adapted from this fine answer.
To be frank, however, I'd find something like this more readable:
cut -d = -f 1 /my/file | tr \\n :
Here's one way using GNU awk:
awk -F= '{ printf "%s:", $1 } END { printf "\n" }' file.txt
Result:
memory:brand:color:battery:
If you don't want a colon after the last word, you can use GNU sed like this:
sed -n 's/=.*//; H; $ { g; s/\n//; s/\n/:/g; p }' file.txt
Result:
memory:brand:color:battery
This might work for you (GNU sed):
sed -i ':a;$!N;s/=[^\n]*\n\?/:/;ta' file
perl -F= -ane '{print $F[0].":"}' your_file
tested below:
> cat temp
abc=def,100,200,dasdas
dasd=dsfsf,2312,123,
adasa=sdffs,1312,1231212,adsdasdasd
qeweqw=das,13123,13,asdadasds
dsadsaa=asdd,12312,123
> perl -F= -ane '{print $F[0].":"}' temp
abc:dasd:adasa:qeweqw:dsadsaa:
My command is
First step:
sed 's/([a-z]+)(\=.*)/\1:/g' Filename |cat >a
cat a
memory:
brand:
color:
battery:
Second step:
sed -e 'N;s/\n//' a | sed -e 'N;s/\n//'
My output is
memory:brand:color:battery: