RS是awk用来定义“行”的,那么FS就是awk用来定义“列”的。
设置变量 FS 与使用 -F 参数是一样的。
kris@letuknowit:~$ echo '1,2' | awk -F , '{print $1}' 1 kris@letuknowit:~$ echo '1,2' | awk 'BEGIN{FS=","}{print $1}' 1
与 RS 类似,FS 同样可以设置为正则表达式
kris@letuknowit:~$ echo '1ab2bc3cd4de5' | awk 'BEGIN{FS="[a-z]+"}{print $1,$2,$5}' 1 2 5
FS 有1个特例,就是将FS设置为一个空格,FS=” ” ,这也是FS的默认值。此时,awk会将连续的 空格 或 制表符(\t) 或 换行符(\n) 作为列的分隔符。
那么,FS=” ” 与 FS=”[ \t\n]+” 有区别么???答案是肯定的!
kris@letuknowit:~$ echo ' 1 2' | awk 'BEGIN{FS=" "}{print $1}' 1 kris@letuknowit:~$ echo ' 1 2' | awk 'BEGIN{FS="[ \t\n]+"}{print $1}'
为了直观一点,下面把每个字段的值都打出来看看
kris@letuknowit:~$ echo ' 1 2' | awk 'BEGIN{FS=" "}{for(i=1;i<=NF;i++)print "$"i"="$i}' $1=1 $2=2 kris@letuknowit:~$ echo ' 1 2' | awk 'BEGIN{FS="[ \t\n]+"}{for(i=1;i<=NF;i++)print "$"i"="$i}' $1= $2=1 $3=2
当FS=” “时,awk会自动去掉行首和行尾的 空格 或 制表符(\t) 或 换行符(\n),但FS=”[ \t\n]+”是不会的。
同样,FS也可以设置为空
kris@letuknowit:~$ echo '123' | awk 'BEGIN{FS=""}{for(i=1;i<=NF;i++)print "$"i"="$i}' $1=1 $2=2 $3=3
当FS被设置为空字符串的时候,awk会将一行记录的每个字符做为单独的一列。
了解的 FS ,我们来看看 OFS ,FS是awk读入记录时的列分隔符,OFS则是awk输出时的列分隔符。
我们平时使用的 print $1,$2 等价于 print $1 OFS $2
kris@letuknowit:~$ echo '1 2' | awk -v OFS="|" '{print $1,$2}' 1|2 kris@letuknowit:~$ echo '1 2' | awk -v OFS="|" '{print $1 OFS $2}' 1|2
如果一行记录有很多列,同时想改变输出的分隔符,print $1,$2,$3 … 岂不是很麻烦?
当然有简单的方法:
kris@letuknowit:~$ echo '1 2 3 4 5' | awk -v OFS="|" '{print $0}' 1 2 3 4 5 kris@letuknowit:~$ echo '1 2 3 4 5' | awk -v OFS="|" '{$1=$1;print $0}' 1|2|3|4|5 kris@letuknowit:~$ echo '1 2 3 4 5' | awk -v OFS="|" '{NF+=0;print $0}' 1|2|3|4|5
为了使OFS的设置生效,需要改变 $0 ,这里我们是对 awk 撒了个小谎。
$1=$1 或者 NF+=0, $0 本身的内容实际上没有任何改变,只是为了使 OFS 的设置生效。
在理解了 RS 和 FS 之后,我们来回顾开始的那句话:“awk是基于行列操作文本的”。这个说法实际上不是很准确,因为在改变了 RS 后,awk 中的“行”已经不是一般的“行”了。同样,改变了 FS 后,awk 中的“列”也已经不是一般的“列”了。
因此,准确的应该这样讲:“awk是基于 记录(record) 和 域(field) 操作文本的”
转载请注明:知识蚂蚁 » awk基础知识:FS 与 OFS 差在哪