给定一个文件 file.txt,转置它的内容。
你可以假设每行列数相同,并且每个字段由 ’ ’ 分隔.
示例:
假设 file.txt 文件内容如下:
name age
alice 21
ryan 30
应当输出:
name alice ryan
age 21 30
答案
awk '{ for(i=1;i<=NF;i++){ if(NR == 1){ a[i] = $i; } else { a[i] = a[i]" "$i; } } }END{ for(i=1;i<=NF;i++){ print a[i]; } }' file.txt
awk是一个非常强大的工具,但是长期依赖,对于awk内部编程,我都搞不太懂。
awk编程是一个什么样的形式?
$ cat cal.awk
#!/bin/awk -f
#运行前
BEGIN {
math = 0
english = 0
computer = 0
printf "NAME NO. MATH ENGLISH COMPUTER TOTAL\n"
printf "---------------------------------------------\n"
}
#运行中
{
math+=$3
english+=$4
computer+=$5
printf "%-6s %-6s %4d %8d %8d %8d\n", $1, $2, $3,$4,$5, $3+$4+$5
}
#运行后
END {
printf "---------------------------------------------\n"
printf " TOTAL:%10d %8d %8d \n", math, english, computer
printf "AVERAGE:%10.2f %8.2f %8.2f\n", math/NR, english/NR, computer/NR
}
实际上就是我begin部分的代码并不对文件进行计算和修改,
对文件进行计算和修改的唯一一个地方是中间的是中括号中的那个代码
最后end中的代码就是,针对前面计算过后之后变量进行输出,或者自定义输出。
如果想要对文本进行处理,处理代码就要放在中间中括号中
针对上面的这道题,如果代码是这样的
awk 'BEGIN {} { for(i=1;i<=NF;i++){ if(NR == 1){ a[i] = $i; } else { a[i] = a[i]" "$i; } } }END{ for(i=1;i<=NF;i++){ print a[i]; } }' file.txt
居然比上面不带begin的代码快好多
这个难以置信
不知道这个是为什么
现在看看awk中的变量以及自定义变量
NF 一条记录的字段的数目
NR 已经读出的记录数,就是行号,从1开始
FILENAME 当前文件名
$0 完整的输入记录
$n 当前记录的第n个字段,字段间由FS分隔
awk '{print(NR,NF);}' log.txt
1 5
2 5
3 3
4 4
5 1
6 3
7 2
awk '{print(FILENAME);}' log.txt
log.txt
log.txt
log.txt
log.txt
log.txt
log.txt
log.txt
居然所有行输出了一遍,因为处理程序部分是针对每行进行处理的。
awk 'BEGIN { print(FILENAME); }' log.txt
放在BEGIN模块,没有输出
awk 'END { print(FILENAME); }' log.txt
log.txt
放在END模块,只有一个输出
其实也就是,变量在后两个代码模块中会起作用,但是在BEGIN模块中不起作用
ofs指定输出分隔符
awk '{print $1,$2,$5}' OFS=" $ " log.txt
2, $ this $ test
3, $ Are $ awk
This's, $ a $
10 $ There, $
987-123-4567 $ $
123 $ 456 $
(123) $ 456-7890 $