Ankur Agarwal
Ankur Agarwal

Reputation: 24768

Controlling sed output when using a script with multiple substitute commands

I have this:

$ cat sedscr 
s/a/A/
s/c/C/
s/n/N/

$ cat file3
#: another
#: bbc
nanco
hello
another

When I do as below I get the output as shown:

$ sed -f sedscr file3
#: ANother
#: bbC
NAnCo
hello
ANother

I don't want hello in the output. How can I do that? The generic question is how do I remove those lines in the output that were not modified at all.

Upvotes: 1

Views: 61

Answers (2)

potong
potong

Reputation: 58438

This might work for you (GNU sed):

sed '/[acn]/!d;y/acn/ACN/' file

If the first condition is not met delete the line otherwise use the translate command.

Or if you prefer:

sed -n '/[anc]/{s/a/A/;s/c/C/;s/n/N/;p}' file

Upvotes: 0

John1024
John1024

Reputation: 113864

General Approach

While a special-case solution for capitalizing letters is included below, in general, we might need all separate s statements. This solution (as improved by Jonathan Leffler) shows how that can be done:

$ sed 's/a/A/; s/c/C/; s/n/N/; t; d' file3
#: ANother
#: bbC
NAnCo
ANother

Notes:

  • s/a/A/; s/c/C/; s/n/N/;

    This does the substitutions

  • t

    If any of the preceding substitutions resulted in a changed line, then the test command, t, jumps to the end of the script at which point the modified line is printed.

    For those who are curious, if we had used more than one t command, then each t command jumps if there had been any substitution since the last t command in the script (per cycle/line). For more complex situations, the t command accepts a label as an argument and would jump to that label.

  • d

    If the jump was not made, then the next command to be executed is d (delete). This removes the line and nothing is printed.

For MacOSX:

sed -e 's/a/A/' -e 's/c/C/' -e 's/n/N/' -e t -e d file3

Special Case of Capitalizing Some Letters

This converts a, n, or c to upper case and prints the line only if a change was made:

$ sed -nr 's/([anc])/\U\1/p' file3
#: Another
#: bbC
Nanco
Another

\U is a GNU extension.

Notes:

  • -n tells sed not to print lines unless we explicitly ask it to.

  • -r asks for extended regex syntax so we don't need so many backslashes. On Mac OSX, use -E instead.

  • s/([anc])/\U\1/p

    This does the substitution which makes the first a, n, or c that appears into upper case. The final p is the explicit command to print the changed lines.

Upvotes: 3

Related Questions