Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Return value of sed for no match

Tags:

json

linux

sed

I'm using sed for updating my JSON configuration file in the runtime. Sometimes, when the pattern doesn't match in the JSON file, sed still exits with return code 0.

Returning 0 means successful completion, but why does sed return 0 if it doesn't find the proper pattern and update the file? Is there a workaround for that?

like image 802
bram Avatar asked Apr 12 '13 07:04

bram


People also ask

What does sed '/ $/ D do?

It means that sed will read the next line and start processing it. nothing will be printed other than the blank lines, three times each. Show activity on this post. The command d is only applied to empty lines here: '/^$/d;p;p'.

Can sed fail?

If the sed command fails, for example, if you try to run it on a file you don't have write access to or one that doesn't exist, sed will exit with a non-0 exit status. The exit status just indicates whether sed managed to do what you told it to do, and echo "foo.

How do I ignore in sed?

escape the '\' so that shell interpreter will expand to a single slash (in the third point below), when defining this variable, use single quotes so it is not expanded, and. expand (by double quoting) when using it within sed, to get the correct end result.

What is I flag in sed?

The I flag allows to match a pattern case insensitively. Usually i is used for such purposes, grep -i for example. But i is a command (discussed in append, change, insert chapter) in sed , so /REGEXP/i cannot be used.


2 Answers

as @cnicutar commented, the return code of a command means if the command was executed successfully. has nothing to do with the logic you implemented in the codes/scripts.

so if you have:

echo "foo"|sed '/bar/ s/a/b/' 

sed will return 0 but if you write some syntax/expression errors, or the input/file doesn't exist, sed cannot execute your request, sed will return 1.

workaround

this is actually not workaround. sed has q command: (from man page):

 q [exit-code] 

here you can define exit-code as you want. For example '/foo/!{q100}; {s/f/b/}' will exit with code 100 if foo isn't present, and otherwise perform the substitution f->b and exit with code 0.

Matched case:

kent$  echo "foo" | sed  '/foo/!{q100}; {s/f/b/}' boo kent$  echo $? 0 

Unmatched case:

kent$ echo "trash" | sed  '/foo/!{q100}; {s/f/b/}' trash kent$ echo $? 100 

I hope this answers your question.

edit

I must add that, the above example is just for one-line processing. I don't know your exact requirement. when you want to get exit 1. one-line unmatched or the whole file. If whole file unmatching case, you may consider awk, or even do a grep before your text processing...

like image 138
Kent Avatar answered Sep 19 '22 13:09

Kent


This might work for you (GNU sed):

sed '/search-string/{s//replacement-string/;h};${x;/./{x;q0};x;q1}' file 

If the search-string is found it will be replaced with replacement-string and at end-of-file sed will exit with 0 return code. If no substitution takes place the return code will be 1.

A more detailed explanation:

In sed the user has two registers at his disposal: the pattern space (PS) in which the current line is loaded into (minus the linefeed) and a spare register called the hold space (HS) which is initially empty.

The general idea is to use the HS as a flag to indicate if a substitution has taken place. If the HS is still empty at the end of the file, then no changes have been made, otherwise changes have occurred.

The command /search-string/ matches search-string with whatever is in the PS and if it is found to contain the search-string the commands between the following curly braces are executed.

Firstly the substitution s//replacement-string/ (sed uses the last regexp i.e. the search-string, if the lefthand-side is empty, so s//replacement-string is the same as s/search-string/replacement-string/) and following this the h command makes a copy of the PS and puts it in the HS.

The sed command $ is used to recognise the last line of a file and the following then occurs.

First the x command swaps the two registers, so the HS becomes the PS and the PS becomes the HS.

Then the PS is searched for any character /./ (. means match any character) remember the HS (now the PS) was initially empty until a substitution took place. If the condition is true the x is again executed followed by q0 command which ends all sed processing and sets the return code to 0. Otherwise the x command is executed and the return code is set to 1.

N.B. although the q quits sed processing it does not prevent the PS from being reassembled by sed and printed as per normal.

Another alternative:

sed '/search-string/!ba;s//replacement-string/;h;:a;$!b;p;x;/./Q;Q1' file 

or:

sed '/search-string/,${s//replacement-string/;b};$q1' file 
like image 36
potong Avatar answered Sep 17 '22 13:09

potong