How to print columns one after the other in bash?

主宰稳场 提交于 2019-12-02 03:46:20

问题


Is there any better methods to print two or more columns into one column, for example

input.file

AAA    111
BBB    222
CCC    333

output:

AAA
BBB
CCC
111
222
333

I can only think of:

cut -f1 input.file >output.file;cut -f2 input.file >>output.file

But it's not good if there are many columns, or when I want to pipe the output to other commands like sort.

Any other suggestions? Thank you very much!


回答1:


With awk

awk '{if(maxc<NF)maxc=NF;
      for(i=1;i<=NF;i++){(a[i]!=""?a[i]=a[i]RS$i:a[i]=$i)}
      }
     END{
      for(i=1;i<=maxc;i++)print a[i]
     }' input.file



回答2:


You can use a GNU awk array of arrays to store all the data and print it later on.

If the number of columns is constant, this works for any amount of columns:

gawk '{for (i=1; i<=NF; i++)            # loop over columns
           data[i][NR]=$i               # store in data[column][line]
      }
      END {for (i=1;i<=NR;i++)          # loop over lines
                for (j=1;j<=NF;j++)     # loop over columns
                     print data[i][j]   # print the given field
      }' file

Note NR stands for number of records (that is, number of lines here) and NF stands for number of fields (that is, the number of fields in a given line).

If the number of columns changes over rows, then we should use yet another array, in this case to store the number of columns for each row. But in the question I don't see a request for this, so I am leaving it for now.

See a sample with three columns:

$ cat a
AAA    111  123
BBB    222  234
CCC    333  345
$ gawk '{for (i=1; i<=NF; i++) data[i][NR]=$i} END {for (i=1;i<=NR;i++) for (j=1;j<=NF;j++) print data[i][j]}' a
AAA
BBB
CCC
111
222
333
123
234
345

If the number of columns is not constant, using an array to store the number of columns for each row helps to keep track of it:

$ cat sc.wk 
{for (i=1; i<=NF; i++)
       data[i][NR]=$i
 columns[NR]=NF
}
END {for (i=1;i<=NR;i++)
            for (j=1;j<=NF;j++)
                 print (i<=columns[j] ? data[i][j] : "-")
}
$ cat a
AAA    111  123
BBB    222
CCC    333  345
$ awk -f sc.wk a
AAA
BBB
CCC
111
222
333
123
-
345



回答3:


awk '{print $1;list[i++]=$2}END{for(j=0;j<i;j++){print list[j];}}' input.file

Output

AAA
BBB
CCC
111
222
333

More simple solution would be

 awk -v RS="[[:blank:]\t\n]+" '1' input.file



回答4:


Expects tab as delimiter:

$ cat <(cut -f 1 asd) <(cut -f 2 asd)
AAA
BBB
CCC
111
222
333



回答5:


Since the order is of no importance:

$ awk 'BEGIN {RS="[ \t\n]+"} 1' file
AAA
111
BBB
222
CCC
333



回答6:


This will work for an arbitrary number fo space separated colums

awk  '{for (A=1;A<=NF;A++) printf("%s\n",$A);}' input.file | sort -u > output.file

If space is not the separateor ... let's suppose ":" is the separator

awk -F: '{for (A=1;A<=NF;A++) printf("%s\n",$A);}' input.file | sort -u > output.file



回答7:


Ugly, but it works-

for i in {1..2} ; do awk -v p="$i" '{print $p}' input.file ; done

Change the {1..2} to {1..n} where 'n' is the number of columns in the input file

Explanation-

We're defining a variable p which itself is the variable i. i varies from 1 to n and at each step we print the 'i'th column of the file.



来源:https://stackoverflow.com/questions/39287224/how-to-print-columns-one-after-the-other-in-bash

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!