简体   繁体   中英

sed command to print a string after certain pattern

Trying to print a string using sed after a line/statement as below,

class name extends #(p val1 = 10,
                     p val2 = 20,
                     p val3 = 30) f_name;


" class " and " extends " and " ; " at the end of that line/statement (ie, consuming multiple lines) will remain constant, rest of the other terms are random.

Expected Result:

class name extends #(p val1 = 10,
                     p val2 = 20,
                     p val3 = 30) f_name;

string t;

Trial done as below,

Trial_command:

sed -i '/^class/a\\string t;'

Trial_Result:

class name extends #(p val1 = 10,
string t;
                     p val2 = 20,
                     p val3 = 30) f_name;


The above command works proper if the class statement ends in the same line as below

class name extends f_name;

But not working when its consumes multiple lines.

Please suggest on this.

Multiline techniques must be used. With GNU sed :

sed -E '/^\s*class\s+\w+\s+extends\b/{ :a; /;\s*$/!{N; ba}; s/$/\nstring t;/ }' file
perl -lpe '$class=1 if /^class/; if ($class and /;$/) { $_ .= "\nstring t;"; $class = 0 }` file

The above command remembers when a line starting with class is seen. Then adds a line string t; and forgets that class is seen, when it sees a line ending with ;.

See https://perldoc.perl.org/perlrun.html for help on various options used.

Ed can do this.

#!/bin/sh

cat >> append.ed << EOF
\$
a

string t;
.
wq
EOF

ed -s filename < append.ed
rm -v ./append.ed

With GNU sed for -z (to read the whole input as a single string) and for \n to mean newline in the replacement text:

$ sed -z 's/class name extends[^;]*;/&\n\nstring t;/' file
class name extends #(p val1 = 10,
                     p val2 = 20,
                     p val3 = 30) f_name;

string t;

otherwise using any awk in any shell on every UNIX box:

$ awk '
    { r = (NR>1 ? r ORS : "") $0 }
    END { sub(/class name extends[^;]*;/,"&\n\nstring t;",r); print r }
' file
class name extends #(p val1 = 10,
                     p val2 = 20,
                     p val3 = 30) f_name;

string t;

This perl one-liner does the job:

perl -0777 -ape 's/\bclass \w+ extends[\s\S]+?;\K/\nstring t;/' file
class name extends #(p val1 = 10,
                     p val2 = 20,
                     p val3 = 30) f_name;
string t;

Explanation:

s/                # substitute
    \b              # word boundary
    class           # literally
    \w+             # 1 or more word characters (class name)
    extends         # literally
    [\s\S]+?        # 1 or more any character including newline
    ;               # semi colon
    \K              # forget all we have seen until this position
/                 # with
    \n              # linefeed
    string t;       # literally
/                 # end subs

This might work for you (GNU sed):

sed '/^class/!b;:a;/;$/!{N;ba};/extends/astring t;' file

If the current line does not begin class , not interested.

If the current line does not end ; , append the next line and repeat.

If the current line(s) contains extended , append another line string t; .


If a blank line then a line containing string t; is required, either:

sed '/^class/!b;:a;/;$/!{N;ba};/extends/G;//astring t;' file

or:

sed '/^class/!b;:a;/;$/!{N;ba};/extends/a\\nstring t;' file

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM