Reputation: 103
the content of a.txt
name age
alice 21
ryan 30
#test.sh
nf=`awk '{print NF; exit}' a.txt`
for((i=1;i<=$nf;i++))
{
awk '{print $i}' ./a.txt
}
The result I expected is print per column,but the actual result is print all content twice.
my expected output is
name
alice
ryan
age
21
30
actual output is
name age
alice 21
ryan 30
name age
alice 21
ryan 30
Upvotes: 2
Views: 185
Reputation: 16997
Another approach using gawk
without saving inside array
, if you prefer saving resource/memory:
awk '
FNR==1 && ++fcount<NF{
delete ARGV[fcount]
ARGV[fcount+1]=FILENAME
ARGC++
}
{
print $(fcount)
}
' file
Results:
$ cat file
name age
alice 21
ryan 30
$ awk 'FNR==1 && ++fcount<NF{delete ARGV[fcount];ARGV[fcount+1]=FILENAME;ARGC++}{print $(fcount)}END{for(i in ARGV)print i,ARGV[i]}' file
name
alice
ryan
age
21
30
Upvotes: 2
Reputation: 203189
You don't need a shell loop, just 1 call to awk. Using any awk in any shell on every Unix box:
$ cat tst.awk
{
for (i=1; i<=NF; i++) {
vals[NR,i] = $i
}
}
END {
for (i=1; i<=NF; i++) {
for (j=1; j<=NR; j++) {
print vals[j,i]
}
}
}
$ awk -f tst.awk a.txt
name
alice
ryan
age
21
30
or, if you prefer, with GNU awk for arrays of arrays:
$ cat tst.awk
{
vals[NR][1]
split($0,vals[NR])
}
END {
for (i=1; i<=NF; i++) {
for (j=1; j<=NR; j++) {
print vals[j][i]
}
}
}
$ awk -f tst.awk a.txt
name
alice
ryan
age
21
30
Upvotes: 1
Reputation: 133428
This could be done in a single awk
itself, please try following; written and tested with your show samples.
awk -v tot="0" '
{
for(i=1;i<=NF;i++){
arr[i]=(arr[i]?arr[i] ORS:"")$i
}
tot=(tot>NF?tot:NF)
}
END{
for(i=1;i<=tot;i++){
print arr[i]
}
}
' Input_file
Explanation: Adding detailed explanation for above.
awk -v tot="0" ' ##Starting awk program from here, setting tot to 0 here.
{
for(i=1;i<=NF;i++){ ##Traversing through all fields here.
arr[i]=(arr[i]?arr[i] ORS:"")$i ##Creating arr with index of i and keep appending current field value in it.
}
tot=(tot>NF?tot:NF) ##Creating tot by seeing current total number of fields, to get highest NF value here.
}
END{ ##Starting END block of this program from here.
for(i=1;i<=tot;i++){ ##Running for loop from i=1 to till tot value here.
print arr[i] ##Printing array with index of i here.
}
}
' Input_file ##Mentioning Input_file name here.
Upvotes: 2
Reputation: 1126
And withawk
without using any array, you can get the expected output:
awk 'NR==FNR{print $1;next}{print $2}' file file
name
alice
ryan
age
21
30
Upvotes: 0
Reputation: 3460
Because your $i
is only visible to bash
, not awk
. You need to pass it into your awk script as:
awk -v i=$i '{print $i}' ./a.txt
The -v
option allows you to pass variables into awk
. i=$i
means the $i
in your awk script will be $i
in your bash.
If other tools are allowed, you can try
cut -f $i a.txt
as a simpler candicate.
Upvotes: 1