Sed replace pattern with line number

I need to replace pattern ### with the current line number.

I managed to print both AWK and SED on the next line.

sed -n "/###/{p;=;}" file prints on the next line without p; , it replaces the entire string.

sed -e "s/###/{=;}/g" file made sense in my head, since =; returns the line number of the matching pattern, but it will return the text {=;} to me

What am I missing? I know this is a stupid question. I could not find the answer to this question in the sed manual, this is not entirely clear.

If possible, tell me what I am missing and what to make it work. thank you

+4
source share
5 answers

A simple awk oneliner:

 awk '{gsub("###",NR,$0);print}' 
+5
source

Given the limitations of the = command , it’s easier for me to split the task into two (in fact, three) parts. Using GNU sed you can:

 $ sed -n '/###/=' test > lineno 

and then something like

 $ sed -e '/###/R lineno' test | sed '/###/{:r;N;s/###\([^\n]*\n\)\([^\n]*\)/\2\1/;tr;:c;s/\n\n/\n/;tc}' 

I am afraid that there is no easy way with sed , because, like the = command, the r and GNU extension r commands do not read files in the template space, but rather directly add lines to the output, so the contents of the file cannot be changed in any way . Therefore, connecting to another sed command.

If the contents of test is equal

 fooo bar ### aa test zz ### bar 

the above will produce

 fooo bar 2 aa test zz 4 bar 
+4
source

As Lev Levitsky noted, this is not possible with one call to sed, because the line number is sent directly to the standard version.

You may have sed write a sed script for you and do the replacement in two passes:

input_file

 a b c d e ### ### ### a b ### c d e ### 

Find the lines containing the pattern:

 sed -n '/###/=' infile 

Output:

 6 7 8 11 15 

A pipe that in sed-script writes a new sed-script:

 sed 's:.*:&s/###/&/:' 

Output:

 6s/###/6/ 7s/###/7/ 8s/###/8/ 11s/###/11/ 15s/###/15/ 

Execute:

 sed -n '/###/=' infile | sed 's:.*:&s/^/& \&/:' | sed -f - infile 

Output:

 a b c d e 6 7 8 a b 11 c d e 15 
+2
source

This may work for you (GNU sed):

 sed = file | sed 'N;:a;s/\(\(.*\)\n.*\)###/\1\2/;ta;s/.*\n//' 
+2
source

this is normal?

 kent$ echo "a b c d e"|awk '/d/{$0=$0" "NR}1' a b c d 4 e 

if the matching pattern is "d", add the line number at the end of the line.

change

oh, you want to replace the template without adding a line number ... look at the new cmd:

 kent$ echo "a b c d e"|awk '/d/{gsub(/d/,NR)}1' a b c 4 e 

and the line can also be written as follows: awk '1+gsub(/d/,NR)' file

+1
source

Source: https://habr.com/ru/post/1435075/


All Articles