How to print columns one after the other in bash?

邮差的信 提交于 2019-12-02 01:47:18

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

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
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

Expects tab as delimiter:

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

Since the order is of no importance:

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

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

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.

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