12

The grep command gives out an exit status:

$echo "foo.bar" | grep -o foo
foo
$echo $?
0
$echo "foo.bar" | grep -o pop
$echo $?
1  

But I need to use sed and I realized that it has no exit status:

$echo "foo.bar" | sed 's/bar.*$//'
foo.
$echo $?
0
$echo "foo.bar" | sed 's/pop.*$//'
foo.bar
$echo $?
0  

I know that I should play around with the -q option, but I have not succeeded.

2
  • 7
    Note that sed most certainly does have an exit status, it just doesn't do what you need here. 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.bar" | sed 's/pop.*$//' was correctly executed. It deleted all lines with pop. That there were no such lines is irrelevant, the command still worked. – terdon May 16 '18 at 13:20
  • @Zanna I was going to post an answer, but I felt this doesn't actually answer the question. It only explains a misconception, but doesn't provide a helpful solution like steeldriver has below. So a comment seemed more appropriate. – terdon May 16 '18 at 15:17
13

You can use qn to quit with exit status n - but to make that useful, you will also need to use some Branching and Flow Control:

t
branch conditionally (that is: jump to a label) only if a s/// command has succeeded since the last input line was read or another conditional branch was taken.

It is probably best to choose a value for n that is distinct from one of the standard exit status values:

An exit status of zero indicates success, and a nonzero value indicates failure. GNU 'sed' returns the following exit status error values:

0
 Successful completion.

1
 Invalid command, invalid syntax, invalid regular expression or a
 GNU 'sed' extension command used with '--posix'.

2
 One or more of the input file specified on the command line could
 not be opened (e.g.  if a file is not found, or read permission is
 denied).  Processing continued with other files.

4
 An I/O error, or a serious processing error during runtime, GNU
 'sed' aborted immediately.

So for example

$ echo "foo.bar" | sed 's/bar.*$//; t; q42' ; echo $? 
foo.
0

whereas

$ echo "foo.bar" | sed 's/baz.*$//; t; q42' ; echo $? 
foo.bar
42

If you want to omit the default printing of the pattern space, then replace q by Q (note that Q is a GNU extension).

1

Here's how to search regex with sed, and highlight matches, or return exit code (5) if no match found:

This is input.txt:

hello there
my dear old friend
a lot of things
we'll pass along the end

Here's my function to Print all + Highlight matches + Return exit code:

highlight()
{
  pattern=$1
  shift
  sed '/'"${pattern}"'/,${s//\x1b[32m&\x1b[0m/g;b};$q5' "$@"
}

$ highlight "lo\|end" input.txt || echo -e "\n* No match found *"

hello there
my dear old friend
a lot of things
we'll pass along the end

When there's no match, it will return exit code (5). You can use it with cat and pipe | as well:

$ cat input.txt | highlight "hot\|and" || echo -e "\n* No match found *"

hello there
my dear old friend
a lot of things
we'll pass along the end

* No match found *

Thanks to https://unix.stackexchange.com/a/405725/43233 - I'm using it + sed quit option.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.