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 差在哪

我来说说

(便于我们更好的交流)

有不明白的地方欢迎留言哦~
取消