shell语法中awk命令的分隔符与匹配模式
awk的分隔符
普通转义字符作为分割符
由于awk底层会有两次转义,因此普通转义字符需要有两个\作为转义标识.如 ∣ | ∣作为分割符时,命令可以被写作:
awk -F '\\$\\|\\$' '{print FNR,$2}' file_dir/test.txt
1 单竖线作为分隔符
文本:
輶$赞兰重隶扶羌悦舍宴 | 扇赞貌因彼坚口命宫竞 | 落用志忠晚能而图业九
昼ww传劳府广靡化叔闰 | 贡往/收此忘遣委谨衡宁 | 横堂敦箴磻旷右溪孟隐
手矫行男仪闲姜成沛手 | 蓝颠异常归殆丽者枝难 | 阶骧必悲新悦诮优盛儿
青连子广寂恐竞羌床知 | 躬连州拜阿子觞辰圣八 | 姜海盛杯者地咸暑疑汉
awk -F ' \\| ' ' {print FNR,$2}' file_dir/test.txt
输出:
1 扇赞貌因彼坚口命宫竞
2 贡往/收此忘遣委谨衡宁
3 蓝颠异常归殆丽者枝难
4 躬连州拜阿子觞辰圣八
2 " ∣ | ∣"作为分割符
文本:
执合塞的明永与写微宠
∣
|
∣池乂槐忘说意隐丙大年
∣
|
∣丁与领荣被稽璇惊莽碣
曰徘增缨骸隐逐想禄抗
∣
|
∣罪思楹几笔阙两盛糟公
∣
|
∣故庄澄珍明跃也疲染龙
旷利载御门更绮机省俶
∣
|
∣慈攸裳详河短规嗣谈称
∣
|
∣修曲刻妍封知人闰楹和
早高人岁笃纨尹穑磻熟
∣
|
∣郁谁诫杯要克龙宜鼓宁
∣
|
∣重即往表敕礼约床在恻
awk -F '\\$\\|\\$' '{print FNR,$2}' file_dir/test.txt
输出
1 池乂槐忘说意隐丙大年
2 罪思楹几笔阙两盛糟公
3 慈攸裳详河短规嗣谈称
4 郁谁诫杯要克龙宜鼓宁
不可见字符作为分割符
不可见字符需要用Unicode码点来表示,如\u2002.但是,awk无法识别这类转义,所以将\u2002转义为字符的操作必须在shell层面完成.当"\u2002|\u2002"用作分割符时,命令可以写作:
awk -F $(echo -e '\u2002')'\\|'$(echo -e '\u2002') '{print FNR,$1,$2,$3}' file_dir/test.txt
不难看出,$(echo -e '\u2002')
在shell层面讲Unicode码制转义为不可见字符,awk拿到的就是字符本身了而不是待转义的码值.
文本:
执合塞的明永与写微宠 | 池乂槐忘说意隐丙大年 | 丁与领荣被稽璇惊莽碣
曰徘增缨骸隐逐想禄抗 | 罪思楹几笔阙两盛糟公 | 故庄澄珍明跃也疲染龙
旷利载御门更绮机省俶 | 慈攸裳详河短规嗣谈称 | 修曲刻妍封知人闰楹和
早高人岁笃纨尹穑磻熟 | 郁谁诫杯要克龙宜鼓宁 | 重即往表敕礼约床在恻
awk -F ' \\| ' ' {print FNR,$2}' file_dir/test.txt
输出:
1
2
3
4
可以看出,直接用空格是无法匹配到\u2002的
$ awk -F '\\u2002\\|\\u2002' '{print FNR,$1,$2,$3}' file_dir/test.txt
输出:
1 执合塞的明永与写微宠 | 池乂槐忘说意隐丙大年 | 丁与领荣被稽璇惊莽碣
2 曰徘增缨骸隐逐想禄抗 | 罪思楹几笔阙两盛糟公 | 故庄澄珍明跃也疲染龙
3 旷利载御门更绮机省俶 | 慈攸裳详河短规嗣谈称 | 修曲刻妍封知人闰楹和
4 早高人岁笃纨尹穑磻熟 | 郁谁诫杯要克龙宜鼓宁 | 重即往表敕礼约床在恻
$ awk -F '\\u2002\\|\\u2002' '{print FNR,$2,$3}' file_dir/test.txt
输出:
1
2
3
4
通过以上两次尝试可以看出,普通转义字符的二次转义在Unicode码点这里也不灵了
$ awk -F $(echo -e '\u2002')'\\|'$(echo -e '\u2002') '{print FNR,$1,$2,$3}' file_dir/test.txt
输出:
1 执合塞逼明永与写微宠 池乂槐忘说意隐丙大年 丁与领荣被稽璇惊莽碣
2 曰徘增缨骸隐逐想禄抗 罪思楹几笔阙两盛糟公 故庄澄珍明跃也疲染龙
3 旷利载御门更绮机省俶 慈攸裳详河短规嗣谈称 修曲刻妍封知人闰楹和
4 早高人岁笃纨尹穑磻熟 郁谁诫杯要克龙宜鼓宁 重即往表敕礼约床在恻
最后,在shell层面完成将转义字符转换为实际的字符,才能实现分隔符匹配
awk的匹配
1 普通字符的正则匹配(支持与或)
文本:
执合塞的明永与写微宠 | 池乂槐忘说意隐丙大年 | 丁与领荣被稽璇惊莽碣
曰徘增缨骸隐逐想禄抗 | 罪思楹几笔阙两盛糟公 | 故庄澄珍明跃也疲染龙
旷利载御门更绮机省俶 | 慈攸裳详河短规嗣谈称 | 修曲刻妍封知人闰楹和
早高人岁笃纨尹穑磻熟 | 郁谁诫杯要克龙宜鼓宁 | 重即往表敕礼约床在恻
awk -F $(echo -e '\u2002')'\\|'$(echo -e '\u2002') '$1 ~ /的/ || $2 ~ /几/{print FNR,$1,$2,$3}' file_dir/test.txt
输出:
1 执合塞的明永与写微宠 池乂槐忘说意隐丙大年 丁与领荣被稽璇惊莽碣
2 曰徘增缨骸隐逐想禄抗 罪思楹几笔阙两盛糟公 故庄澄珍明跃也疲染龙
awk -F $(echo -e '\u2002')'\\|'$(echo -e '\u2002') '$1 ~ /的/ && $2 ~ /大/{print FNR,$1,$2,$3}' file_dir/test.txt
输出:
1 执合塞的明永与写微宠 池乂槐忘说意隐丙大年 丁与领荣被稽璇惊莽碣
2 转义字符的正则匹配
文本:
001 | 面包 | 10
002 | 牛奶 | 12
004 | 蛋糕 | 101
$ awk -F $(echo -e '\u2002')'\\|'$(echo -e '\u2002') '$2 ~ /\t/ {print $0}' test.txt > newtest.txt;cat newtest.txt
输出:
004 | 蛋糕 | 101
3 数字的模式匹配
文本:
001 | 面包 | 10
002 | 牛奶 | 12
004 | 蛋糕 | 101
awk -F $(echo -e '\u2002')'\\|'$(echo -e '\u2002') '$3 < 12 {print $0}' test.txt > newtest.txt;cat newtest.txt
输出:
001 | 面包 | 10
4 用Unicode码点匹配不可见字符
echo -e '1\u20023' | awk '$1 ~ /\u2002/ {print $0}'
无返回
echo -e '1\u20023' | awk '$1 ~ v1 {print $0}' v1=`echo -e '\u2002'`
输出:1 3
还是同样的原因,还是同样的解决方法