Sed or awk: how to call line addresses from a separate file?

I have 'file1' with (say) 100 lines. I want to use sed or awk to print lines 23, 71 and 84 (for example) into the file 'file2'. These 3 line numbers are in a separate file, a β€œlist”, each number of which is on a separate line.

When I use any of these commands, only line 84 is printed:

for i in $(cat list); do sed -n "${i}p" file1 > file2; done for i in $(cat list); do awk 'NR==x {print}' x=$i file1 > file2; done 

Can a for loop be used this way to feed line addresses to sed or awk?

+4
source share
5 answers

This may work for you (GNU sed):

 sed 's/.*/&p/' list | sed -nf - file1 >file2 

Use list to build a sed script.

+5
source

After the loop, you need to do > to capture everything. Since you use it inside a loop, the file is overwritten. Inside the loop you need to do >> .

It’s good practice to use or use > outside the loop so that the file is not open for writing during each iteration of the loop.

However, you can do everything in awk without for loop .

 awk 'NR==FNR{a[$1]++;next}FNR in a' list file1 > file2 
+4
source

You need >> (add to file). But you are overwriting the file. This is why you always get 84 lines in file2 only.

Try using

 for i in $(cat list); do sed -n "${i}p" file1 >> file2; done 
+3
source

With sed:

  sed -n $(sed -e 's/^/-e /' -e 's/$/p/' list) input 

given an example input, an internal command creates a line like this: `

 -e 23p -e 71p -e 84p 

so external sed then prints the given lines

+3
source

You can avoid using sed / awk in the for / while loop alter:

 # store all lines numbers in a variable using pipe lines=$(echo $(<list) | sed 's/ /|/g') # print lines of specified line numbers and store output awk -v lineS="^($lines)$" 'NR ~ lineS' file1 > out 
+1
source

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


All Articles