Not getting an sed error - linux

Im trying to append a line in a file using following sed command
sed -i 's/id="1asda"/id="1asda"\n peer="120"/g' a.xml.
Now the problem is that even if I'm giving a wrong id, sed is not popping an error.How to get an error if the pattern is not found.

sed is used to replace text. Having nothing to replace is not an error.
Use something like grep to check whether there's something to replace or not. For example:
if grep -q 'id="1asda"' a.xml
then
sed -i 's/id="1asda"/id="1asda"\n peer="120"/g' a.xml
else
echo 'nothing to do' >& 2
fi

I would suggest to use awk:
awk 'BEGIN{e=1}gsub(/foo1/, "bar",$0){e=0};1;END{exit e}' file
The above command will give you a return value of 1 if no substitution has been performed, otherwise 0.

Related

Sed not working in usual way - Shell scripting

I have two sed command which includes in my cook.sh script. One command is
sed -E -i "s/^(\\\$mainDomain=\")[^\"]+(\";)$/\1$MainDomain\2/" /var/config.php
This is working fine.
But the below command which is almost same. But it is not working.
sed -E -i "s/^(\\\$authURI=\")[^\"]+(\";)$/\1$duo_auth\2/" /var/config.php
That give the below error message
sed: -e expression #1, char 36: unknown option to `s'
Any idea on this ?
The issue is likely due to your replacement variable $duo_auth having a un-escaped /, change the default sed separator from / to ~ as
sed -E -i "s~^(\\\$authURI=\")[^\"]+(\";)$~\1$duo_auth\2~" /var/config.php
Try it without -i for seeing if the replacement is as expected and put it back after confirmation.
Example:-
cat /var/config.php
<?php
$authURI="dev.digin.io";
now setting the variable
duo_auth="http://auth.uri.digin.io:3048/"
Now the replacement, without -i
sed -E "s~^(\\\$authURI=\")[^\"]+(\";)$~\1$duo_auth\2~" /var/config.php
<?php
$authURI="http://auth.uri.digin.io:3048/";
The problem is probably due to $duo_auth containing an unescaped /. This means that the sed editing script will have a syntax error.
You may pick any other character to use as a delimiter in the s/.../.../ command, for example #:
sed "s#....#....#"
Just make sure that you pick a character that is not ever going to turn up in either $duo_auth or $authURI.
While testing, I'd recommend that you avoid using in-place-editing (-i) with sed. Also, the -i switch is horribly non-portable between sed implementations (some requires an argument).
Instead, do the slightly more cumbersome
sed -e "s#...#...#" data.in >data.in.tmp && mv -f data.in.tmp data.in
While testing, check the data.in.tmp file before moving it.

CentOS - displaying 1 line of file only

echo "Enter line number to display"
read number
sed -n $number /etc/passwd
I need to display only one line of text given by the user, in possible easy way. Above line is giving me error:
sed -e expression char3,extra characters after command.
What am I doing wrong?
Thanks
the correct command is:
sed -n ${number}p /etc/passwd
(p is command to print)
Of course sed will do nothing useful after that, so it's even better to quit after having printed like Benjamin hinted to avoid reading the rest of the file:
sed -n ${number}'{p;q}' /etc/passwd

Append text to file without line breaking

On a Linux machine, I have list of IPs as follows:
107.6.38.55
108.171.207.62
108.171.244.138
108.171.246.87
I want to use some function to add the word "or" at the end of each line without breaking each line, like this:
107.6.38.55 or
108.171.207.62 or
108.171.244.138 or
108.171.246.87 or
Every implementation I have experimented with in sed or awk has given me incorrect results as it keeps trying to line break or add input in strange spots. What is the easiest way to achieve this goal?
With awk '$0=$0" or"' and the sed suggestions I've tried thus far I get the following formatting:
107.6.38.55
or
108.171.207.62
or
108.171.244.138
or
108.171.246.87
or
Not sure what you have been trying but the following works for me on Ubuntu 12.04
awk '{print $0" or"}'
Or as fedorqui suggests
awk '$0=$0" or"'
Or as glenn jackman suggests
awk '{print $0, "or"}'
[EDIT]
It turns out the OP's file had CRLF line breaks so dos2unix had to be run first to address the format issue
The following two worked for me:
sed 's/.*/& or/'
sed 's/$/ or/'
Or use ed, the standard text editor:
With bash you can use the lovely here-strings together with ANSI-C quotings
ed -s filename <<< $',s/.$/& or/\nwq'
or a pipe with printf
printf "%s\n" ',s/.$/& or/' 'wq' | ed -s filename
or if you like echo better
{ echo ',s/.$/& or/'; echo "wq"; } | ed -s filename
or interactively (if you love question marks):
$ ed filename
,s/.$/& or/
wq
Remark. I'm using the substitution s/.$/& or/ and not s/$/ or/ just so as not to append or in an empty line.

Sed Append Line

Does sed have a command to append a line after a matched line? I tried searching around but was a bit confused with the results.
Basiclly I want it to match
#address=/doubleclick.net/127.0.0.1
And add a line below it like
#address=/doubleclick.net/127.0.0.1
address=/anotherurl/ipaddress
Is this possible?
You can use the a(append) command in sed:
$ sed -i '/^#address=\/doubleclick.net\/127.0.0.1$/a\
> address=/anotherurl/ipaddress' file.txt
Or you can use s(substitute) command:
$ sed -i 's#^#address=/doubleclick.net/127.0.0.1$#&\naddress=/anotherurl/ipaddress#' file.txt
Note: $ and > are bash prompt.
This might work for you:
echo "#address=/doubleclick.net/127.0.0.1"|
sed '\|#address=/doubleclick.net/127.0.0.1|a\address=/anotherurl/ipaddress'
#address=/doubleclick.net/127.0.0.1
address=/anotherurl/ipaddress
You can use any delimiter you like in an address by prepending a \ i.e. \|...| for the substitute command the \ is not necessary.
If you want a blank line then some text following the match, use:
echo "#address=/doubleclick.net/127.0.0.1"|
sed '\|#address=/doubleclick.net/127.0.0.1|a\\naddress=/anotherurl/ipaddress'
#address=/doubleclick.net/127.0.0.1
address=/anotherurl/ipaddress

Trying to pass regular expression to grep

I'm trying to exctract error lines from my log file:
I used this :
more report.txt | grep -E (?i)(error)
I'm getting this error msg :
bash: syntax error near unexpected token `('
What am I doing wrong? I'm trying to extract all lines containing "Error" ignoring the case sensitivity so it can be error, Error, ERROR etc.
The problem with your line is that the parens are picked up by the shell instead of grep, you need to quote them:
grep -E '(?i)(error)' report.txt
For this particular task the other answers are of course correct, you don't even need the parens.
You can do:
grep -i error report.txt
There is really no need to more the file and then pipe it to grep. You can pass the filename as an argument to grep.
To make the search case insensitive, you use the -i option of grep.
And there is really no need to go for -E option as the pattern you are using error is not an extended regex.
The cause of the error you are seeing is that your pattern (?i)(error) is interpreted by the shell and since the shell did not except to see ( in this context it throws an error, something similar to when you do ls (*).
To fix this you quote your pattern. But that will not solve your problem of finding error in the file because the pattern (?i)(error) looks for the string 'ierror' !!
you can use
grep -i error report.txt
this will achieve the same result
cat report.txt | grep -i error
and if you want to paginate the results:
cat report.txt | grep -i error | more

Resources