5

Suppose I have 2 Files, ABC.txt & PQR.txt with the data shown below as an example:

ABC.txt:

ABC DEF

PQR.txt:

PQR XYZ

I want to grep column 1 from both files and write into a third text file. How can it be done?

My expected output is (output.txt):

ABC PQR
  • Do you really mean UNIX? What OS are you running? Of the answers here, only the awk approach uses non-GNU tools so I am not sure they will work on a UNIX. They all work fine on any Linux. – terdon Nov 10 '14 at 14:24
7

Here are a couple of ways:

  • Using paste and cut :

    $ paste -d ' ' <(cut -d' ' -f 1 ABC.txt ) <(cut -d' ' -f 1 PQR.txt ) > output.txt
    ABC PQR
    

    If your system does not support process substitution, use this instead:

    $ cut -d' ' -f 1 ABC.txt > /tmp/aa; cut -d' ' -f 1 PQR.txt > /tmp/bb; paste -d ' ' /tmp/aa /tmp/bb
    
  • Using awk (thanks @Costas):

    awk 'FNR==NR{a[FNR]=$1; next}{print a[FNR],$1}' ABC.txt PQR.txt > output.txt
    

    The special variable FNR is the line number of the current input file and NR is the line number of the input in general, whatever file it came from. The two are equal only while the first input file is being read. So, the first fields of the first file are saved in the a array (a[FNR]=$1) whose keys are line numbers and whose values are the 1st fields. Then, when the second file is reached, we print the value corresponding to its line number (a[NR]) and the current line's 1st field.

5

You can numerate lines by nl and use join

join -o 1.2,2.2 <(nl ABC.txt) <(nl PQR.txt) > OUT.file

Or by cat -n

join -o 1.2,2.2 <(cat -n ABC.txt) <(cat -n PQR.txt) > OUT.file

Like Parse two files input in for/while loop you can use just bash builtins

while read -u 3 a b && read -u 4 c d
do
  echo "$a $c"
done 3< ABC.txt 4< PQR.txt >OUT.txt
  • For Join Answer I am getting Error as below .. ksh: syntax error: `(' unexpected I am using ksh shell – Rahul Patil Nov 12 '14 at 9:51
  • @RahulPatil Process Substitution. This feature is only available on versions of the UNIX operating system that support the /dev/fd directory for naming open files. Each command argument of the form <(list) or >(list) will run process list asynchronously connected to some file in /dev/fd. – Costas Nov 12 '14 at 10:03
4

Assuming the fields are separated by a single space in the input files, I would write:

paste -d " " ABC.txt PQR.txt | cut -d " " -f 1,3 > Output.txt

To handle arbitrary whitespace, and more than 2 columns per file, and assuming your shell is bash/ksh/zsh(?)

paste -d " " <(awk '{print $1}' ABC.txt) <(awk '{print $1}' PQR.txt) > Output.txt
  • For First Answer I am getting output as ABC only.... For Second Answer I am getting below Error ksh: syntax error: `(' unexpected I am using ksh shell – Rahul Patil Nov 12 '14 at 9:49
  • In the input files, what is the field separator? What version of ksh are you using? – glenn jackman Nov 12 '14 at 11:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.