简体   繁体   中英

Copying a line from one file to another in bash

I'm trying to copy a line from file1 and write that line into line 10 of file2 using bash.

Here is what I have tried:

sed -e '10i' file2 <file1

You can do this using awk:

awk 'NR==1{a=$0}NR==FNR{next}FNR==10{print a}1' file1 file2

NR keeps a count of the overall line number. This is only equal to 1 for the first line of the first file. The contents of the line is stored in a variable a .

FNR keeps a count of the line number of the current file. NR and FNR are equal (ie we are in file1), next skips to the next line, which means that for every other line in the first file, nothing happens.

The final block is executed at line 10 of the second file, inserting the value of a . The 1 at the end is a common shorthand which means that every line of the file is printed.

Testing it out:

$ cat file1
line 1 in file1
line 2 in file1    
$ cat file2
line 1 in file2
line 2 in file2
line 3 in file2
line 4 in file2
line 5 in file2
line 6 in file2
line 7 in file2
line 8 in file2
line 9 in file2
line 10 in file2
$ awk 'NR==1{a=$0}NR==FNR{next}FNR==10{print a}1' file1 file2
line 1 in file2
line 2 in file2
line 3 in file2
line 4 in file2
line 5 in file2
line 6 in file2
line 7 in file2
line 8 in file2
line 9 in file2
line 1 in file1
line 10 in file2

To overwrite the original contents of file2, you can redirect the output to a temporary file like awk '...' file1 file2 tmp && mv tmp file2 .

I'm not sure where you want your lines to come from and go to, but you could do this:

sed 'NUMq;d' file1 >>file2

replacing NUM with the number of the line you want from file1 to append to file2.

EDIT

I think this is what you want:

sed -i .bak "10 i\\
`sed 1q\;d file1`
" file2

If you are using GNU sed , this:

sed -n '1p' choose-line-here.txt | sed -i '10r /dev/stdin' insert-here.txt

will insert line 1 from choose-line-here.txt after line 10 in insert-here.txt .

Changing line 10 seems to be trickier, surprisingly. I've come up with this so far:

sed -n 1p choose-line-here.txt |
sed -e '9!b' -e 'N;s/\n.*//;r /dev/stdin' insert-here.txt

The tricky part is, that the r command inserts the contents of /dev/stdin , that is, standard input, after the current line. If that is the line which is to be replaced, then I don't see a way to get rid of it without outputting a spare newline. Therefore the trick to start the insertion in the previous line, line 9 in this case.

A simpler solution for changing the target line is possible, if one relies on sed not counting the freshly read line from stdin:

sed -n 1p choose-line-here.txt |
sed -i -e '9r /dev/stdin' -e '10d' insert-here.txt

This might work for you (GNU sed & Bash):

sed $'10{e sed "1!d" file1\n;d}' file2

or another way using a pipe:

sed '1!d' file1 | sed -e '10{r /dev/stdin' -e 'd}' file2

or a third way (perhaps more intuitively but only works for a singleton replacement line):

sed '10\c'$(sed '1!d' file1) file2

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