Transpose File
Total Accepted: 3876
Total Submissions: 18849
Difficulty: Medium
Contributors: Admin
Given a text file file.txt, transpose its content.
You may assume that each row has the same number of columns and each field is separated by the ’ ’ character.
For example, if file.txt has the following content:
name age
alice 21
ryan 30
Output the following:
name alice ryan
age 21 30
Subscribe to see which companies asked this question
#!/bin/bash
declare -A line
awk '
{
for(i=1;i<=NF;i++)
{
line[i] = line[i]" "$i
}
}
END{
for(j=1;j<=NF;j++) {
print line[j]
}
}
' t13-file.txt
注意格式END后面紧跟{
或者如下:
#!/bin/bash
awk '
{
for(i=1; i<=NF; i++)
{
if(line[i] == "")
{
line[i] = $i
}
else
{
line[i] = line[i]" "$i
}
}
}
END{
for(i=1; i<=NF; i++)
{
print line[i]
}
}
' t12-file.txt
怎么理解这个呢?调试如下:
#!/bin/bash
awk '
{
for(i=1; i<=NF; i++)
{
print ("line current: ",line[i])
if(line[i] == "")
{
line[i] = $i
print ("NR value: ",NR)
print (" line[i] i :",i)
print "1" line[i]
print ("i :",i)
}
else
{
line[i] = line[i]" "$i
print "else $i : " $i
print "else line "line[i]
print ("else NR value: ",NR)
print ("else i :",i)
}
}
}
END{
print ("===== ")
print ("NF value: ",NF)
print ("NR value: ",NR)
for(i=1; i<=NF; i++)
{ print ("NR tail value: ",NR)
print ("i:line ",i,line[i])
}
}
' t12-file.txt
结果:
root@ubuntu:~/test# ./t12-try.sh
line current:
NR value: 1
line[i] i : 1
1name
i : 1
line current:
NR value: 1
line[i] i : 2
1age
i : 2
line current: name
else $i : alice
else line name alice
else NR value: 2
else i : 1
line current: age
else $i : 21
else line age 21
else NR value: 2
else i : 2
line current: name alice
else $i : ryan
else line name alice ryan
else NR value: 3
else i : 1
line current: age 21
else $i : 30
else line age 21 30
else NR value: 3
else i : 2
=====
NF value: 2
NR value: 3
NR tail value: 3
i:line 1 name alice ryan
NR tail value: 3
i:line 2 age 21 30
如结果看到的,line是个新的数组,line有两条记录(line[
1]和line[
2]),每条记录是3列。awk每次处理一条记录,这里一条记录是2列(2个元素:
1,
2)。
line[1]=第{1-NR}条记录的
1拼接line[2]=第1−NR条记录的
2拼接
或许你会想到:
root@ubuntu:~/test# cut -d " " -f 1 t12-file.txt |xargs
name alice ryan
root@ubuntu:~/test# cut -d " " -f 2 t12-file.txt |xargs
age 21 30
继而有个想法,这个想法是不正确的如下:
#!/bin/bash
i=1
echo "1st output i : $i"
awk -F " " '{print $i}' t12-file.txt |xargs
echo "$i"
let i=i+1
echo "add i : $i"
awk -F " " '{print $i}' t12-file.txt |xargs
echo "$i"
执行结果:
root@ubuntu:~/test# ./t12.sh
1st output i : 1
name age alice 21 ryan 30
1
add i : 2
name age alice 21 ryan 30
2
那么为什么i没有按照所预计的输出呢?
因为i没有传进awk里面。看下面的两个例子,是可以正确输出结果的:
#!/bin/bash
awk -F" " 'BEGIN{i=1}{print $i}' t12-file.txt |xargs
awk -F" " 'BEGIN{i=2} {print $i}' t12-file.txt |xargs
print "################################"
i=1
awk -F" " '{print $field}' field=$i t12-file.txt |xargs
((i++))
awk -F" " '{print $field}' field=$i t12-file.txt |xargs
在awk外面给i 赋值,没有传进awk内,awk内的i是没有值的。
所以必须在awk里面赋值。
验证:在awk中一打印i,确实没值。
awk不接受外面的值,但是cut是可以。外层循环的i可以直接传给cut:
#!/bin/ksh
typeset number
number=$(awk '{num=NF} END{print num}' t12-file.txt)
for ((i=1;i<=$number;i++ ));
do
cut -d " " -f $i t12-file.txt |xargs
done