I wrote a script for interweaving contents of two files. The script goes like this
#!/bin/bash
touch t_10.txt
numer1=$(cat $1 | wc -l)
numer2=$(cat $2 | wc -l)
count=1
while [ $count -le $numer1 -a $count -le $numer2 ]
do
head -n $count $1 | tail -n 1 >> merge.txt
head -n $count $2 | tail -n 1 >> merge.txt
count=$((count 1))
done
count=$((count-1))
if [ $count -lt $numer1 ]; then
rem=$(( $numer1 - $count ))
tail -n $rem $1 >> merge.txt
else
rem=$(( $numer2 - $count ))
tail -n $rem $2 >> merge.txt
fi
Can you tell me if there is any better cli utility??
CodePudding user response:
Please read why-is-using-a-shell-loop-to-process-text-considered-bad-practice. The guys who invented shell
to create/destroy files and processes and sequence calls to tools also invented awk
for shell
to call to manipulate text.
$ head file{1,2}
==> file1 <==
foo 1
foo 2
foo 3
foo 4
foo 5
==> file2 <==
BAR 1
BAR 2
BAR 3
$ cat tst.awk
BEGIN {
file2 = ARGV[2]
ARGV[2] = ""
ARGC--
}
{ print }
(getline < file2) > 0
END {
while ( (getline < file2) > 0 ) {
print
}
}
$ awk -f tst.awk file1 file2
foo 1
BAR 1
foo 2
BAR 2
foo 3
BAR 3
foo 4
foo 5
$ awk -f tst.awk file2 file1
BAR 1
foo 1
BAR 2
foo 2
BAR 3
foo 3
foo 4
foo 5
This is one of the rare occasions where it's appropriate to use getline
, see http://awk.freeshell.org/AllAboutGetline.
CodePudding user response:
Try the following.
paste file1 file2 |tr "\t" "\n" >> merge.txt
CodePudding user response:
Just for fun in pure bash, making good use of array indexes, interleaving an arbitrary number of file arguments:
#!/bin/bash
fd=( stdin stdout stderr "$@" )
unset fd[0] fd[1] fd[2]
for i in "${!fd[@]}"
do
eval "exec $i< $(printf %q "${fd[i]}")" || unset fd[i] # you could exit instead
done
until ${eof-false}
do
eof=true
for i in "${!fd[@]}"
do
if eval "IFS='' read -r line <&$i"
then
printf '%s\n' "$line"
eof=false
else
unset fd[i]
eval "exec $i<&-"
fi
done
done
note: The good part is that this code won't try to read more bytes in a file after reaching its end.
I wonder if you can do it without eval
.