简体   繁体   中英

How to fill empty lines from one file with corresponding lines from another file, in BASH?

I have two files, file1.txt and file2.txt . Each has an identical number of lines, but some of the lines in file1.txt are empty. This is easiest to see when the content of the two files is displayed in parallel:

file1.txt     file2.txt
cat           bear
fish          eagle
spider        leopard
              snail
catfish       rainbow trout
              snake
              koala
rabbit        fish

I need to assemble these files together, such that the empty lines in file1.txt are filled with the data found in the lines (of the same line number) from file2.txt . The result in file3.txt would look like this:

cat
fish
spider
snail
catfish
snake
koala
rabbit

The best I can do so far, is create a while read -r line loop, create a counter that counts how many times the while loop has looped, then use an if-conditional to check if $line is empty, then use cut to obtain the line number from file2.txt according to the number on the counter. This method seems really inefficient.

  • Sometimes file2.txt might contain some empty lines. If file1.txt has an empty line and file2.txt also has an empty line in the same place, the result is an empty line in file3.txt .

How can I fill the empty lines in one file with corresponding lines from another file?

paste file1.txt file2.txt | awk -F '\t' '$1 { print $1 ; next } { print $2 }'

Here is the way to handle these files with awk :

awk 'FNR==NR {a[NR]=$0;next} {print (NF?$0:a[FNR])}' file2 file1
cat
fish
spider
snail
catfish
snake
koala
rabbit

First it store every data of the file2 in array a using record number as index
Then it prints file1 , bit it thest if file1 contains data for each record
If there is data for this record, then use it, if not get one from file2

一个与getline(在这种情况下无害):

awk '{getline p<f; print NF?$0:p; p=x}' f=file2 file1

Just for fun:

paste file1.txt file2.txt | sed -E 's/^   //g' | cut -f1

This deletes tabs that are at the beginning of a line (those missing from file1) and then takes the first column.

(For OSX, \\t doesn't work in sed, so to get the TAB character, you type ctrl-V then Tab)

Here is a Bash only solution.

for i in 1 2; do
    while read line; do
        if [ $i -eq 1 ]; then
            arr1+=("$line")
        else
            arr2+=("$line")
        fi
    done < file${i}.txt
done
for r in ${!arr1[@]}; do
    if [[ -n ${arr1[$r]} ]]; then
            echo ${arr1[$r]}
    else
            echo ${arr2[$r]}
    fi
done > file3.txt

没有awk的解决方案:

paste -d"#" file1 file2 | sed 's/^#\(.*\)/\1/' | cut -d"#" -f1

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