how to replace the first line of a file with the first line of another file [duplicate] - bash

This question already has answers here:
Replace first few lines with first few lines from other file
(3 answers)
Closed 4 years ago.
i have 2 txt files : file1 and file2
i would like to replace the first line of file2 with the first line of file1, with a bash command
file1:
aaaaaaaa
bbbbbbbb
cccccccc
file2:
zzzzzzzz
yyyyyyyy
wwwwwwww
expected result of file2:
aaaaaaaa
yyyyyyyy
wwwwwwww
this can't be done with sed as you don't know what to replace with what...i'm right? so how to do this ?
EDIT:
so in my particular case (i do it in my openwrt router), what worked is :
sed -i "1c $(sed 1q file1)" file2
Thanks to #Sundeed for the link explaining why some commands were only displaying the results in the shell but not writing in the file : https://mywiki.wooledge.org/BashPitfalls#cat_file_.7C_sed_s.2Ffoo.2Fbar.2F_.3E_file

This might work for you (GNU sed):
sed -e '1R file1' -e '1d' file2
Read the first line of file2. Read the first line of file1 and insert it into the output, then delete the first line of file2. Now read and output the rest of file2.

Simply use head and tail for this task:
head -n 1 Input_file1 && tail -n 2 Input_file2
Output will be as follows:
aaaaaaaa
yyyyyyyy
wwwwwwww

You certainly can do this with sed, but why would you?
sed "1c\\
$(sed 1q file1)
" file2

Or with ed
f1="file1";f2="file2";printf "%s\n" '2,$d' "r $f2" '2d' "wq $f2" | ed -s "$f1"

Related

How to copy specific lines from file 1 after specific line from file 2?

I have a file1 and a file2.
I want to copy lines 3,4,5 of file1 into file2, but after line 3.
I tried this, but it didn't work:
sed -i 3r<(sed '3,5!d' file1) file2
Any ideas? (I work with a macOS)
Example file1:
_line_1;
_line_2;
_line_3;
_line_4;
_line_5;
Example file2:
line1;
line2;
line3;
line4;
Example output
line1;
line2;
line3;
_line_3;
_line_4;
_line_5;
line4;
This might work for you (GNU sed):
sed -n '3,5p' file1 | sed '3r /dev/stdin' file2
Turn off implicit printing in the first sed invocation and pipe the results (lines 3-5) from file1 to a second sed invocation that reads in these lines after line 3 of file2.
Using a mix of ed and sed:
printf "%s\n" '3r !sed -n 3,5p file1' w | ed -s file2
Inserts the results of the sed command after line 3 of file2. Said sed prints out lines 3 through 5 of file1. Then it saves the changed file2.
With only ed if it's allowed
printf "%s\n" "kx" "r file1" "'x+3,'x+5m3" "'x+1,\$d" "w" | ed -s file2
Here the k command mark the last line of file2.
You must protect the $ to the shell.

Bash - reading two files and searching within files

I have two files, file1 and file2. I want to reach each line from file1, and then search if any of the lines in file2 is present in file1. I am using the following bash script, but it does not seem to be working. What should I change? (I am new to bash scripting).
#!/bin/bash
while read line1
do
echo $line1
while read line2
do
if grep -Fxq "line2" "$1"
then
echo "found"
fi
done < "$2"
done < "$1"
Note: Both files are text files.
Use grep -f
grep -f file_with_search_words file_with_content
Note however that if file_with_search_words contains blank lines everything will be matched. But that can be easily avoided with:
grep -f <(sed '/^$/d' file_with_search_words) file_with_content
From the man page:
-f FILE, --file=FILE
Obtain patterns from FILE, one per line. If this option is used
multiple times or is combined with the -e (--regexp) option, search
for all patterns given. The empty file contains zero patterns, and
therefore matches nothing.
You may use the command "comm", it compare two sorted files line-by-line
This command show the common lines in file1 and file2
comm -12 file1 file2
The only problem with this command is that you have to sort the files before, like this:
sort file1 > file1sorted
http://www.computerhope.com/unix/ucomm.htm
File 1
Line 1
Line 3
Line 6
Line 9
File 2
Line 3
Line 6
awk 'NR==FNR{con[$0];next} $0 in con{print $0}' file1 file2
will give you
Line 3
Line 6
that is the content in file 2 which is present in file1.
If you wish to ignore the spaces you can achieve with the below one.
awk 'NR==FNR{con[$0];next} !/^$/{$0 in con;print $0}' file1 file2

remove lines based on file input pattern using sed

I have been trying to solve a simple sed line deletion problem.
Looked here and there. It didn't solve my problem.
My problem could simply be achieved by using sed -i'{/^1\|^2\|^3/d;}' infile.txt which deletes lines beginning with 1,2 and 3 from the infile.txt.
But what I want instead is to take the starting matching patterns from a file than manually feeding into the stream editor.
E.g: deletePattern
1
3
2
infile.txt
1 Line here
2 Line here
3 Line here
4 Line here
Desired output
4 Line here
Thank you in advance,
This grep should work:
grep -Fvf deletePattern infile.txt
4 Line here
But this will skip a line if patterns in deletePattern are found anywhere in the 2nd file.
More accurate results can be achieved by using this awk command:
awk 'FILENAME == ARGV[1] && FNR==NR{a[$1];next} !($1 in a)' deletePattern infile.txt
4 Line here
Putting together a quick command substitution combined with a character class will allow a relatively short oneliner:
$ sed -e "/^[$( while read -r ch; do a+=$ch; done <pattern.txt; echo "$a" )]/d" infile.txt
4 Line here
Of course, change the -e to -i for actual in-place substitution.
With GNU sed (for -f -):
sed 's!^[0-9][0-9]*$!/^&[^0-9]/d!' deletePattern | sed -f - infile.txt
The first sed transforms deletePattern into a sed script, then the second sed applies this script.
Try this:
sed '/^[123]/ d' infile.txt

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 (i.e. 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

Unix: One line bash command to merge 3 files together. extracting only the first line of each

I am having time with my syntax here:
I have 3 files with various content file1 file2 file3 (100+ lines). I am trying to merge them together, but only the first line of each file should be merged. The point is to do it using one line of bash code:
sed -n 1p file1 file2 file3 returns only the first line of file1
You might want to try
head -n1 -q file1 file2 file3.
It's not clear if by merge you mean concatenate or join?
In awk by joining (each first line in the files printed side by side):
$ awk 'FNR==1{printf "%s ",$0}' file1 file2 file3
1 2 3
In awk by concatenating (each first line in the files printed one after another):
$ awk 'FNR==1' file1 file2 file3
1
2
3
I suggest you use head as explained by themel's answer. However, if you insist in using sed you cannot simply pass all files to it, since they are implicitly concatenated and you lose information about what the first line is in each file respectively. So, if you really want to do it in sed, you need bash to help you out:
for f in file1 file2 file3; do sed -n 1p "$f"; done
You can avoid calling external processes by using the read built-in command:
for f in file1 file2 file3; do read l < $f; echo "$l"; done > merged.txt

Resources