如何使用 unix 终端打印一行的每个二元组?标点符号被视为一个“单词”。
例如,如果我必须输入以下内容:
This is ! line .
This is ! second line .
如果搜索每个二元组,我的输出应该如下:
This is
is !
! line
line .
This is
is !
! second
second line
line .
如果搜索每个三元组,我的输出应该如下:
This is !
is ! line
! line .
this is !
is ! second
! second line
second line .
命令
grep -Eio '[a-z!.]+ [a-z!.]+'
退货
This is
! line
This is
! second
line .
这很接近,但还不是我需要的。
答案1
你可以像这样使用perl
二元组
perl -lne 'while(/(\S+\s+\S*){1}/){print $&;s/\S+\s+//}' file
This is
is !
! line
line .
This is
is !
! second
second line
line .
卦象
perl -lne 'while(/(\S+\s+\S*){2}/){print $&;s/\S+\s+//}' file
This is !
is ! line
! line .
This is !
is ! second
! second line
second line .
将大括号中的数字更改为每行所需的数量 (-1)。
答案2
您需要一个grep
不仅能够打印部分行的实现(就像您的 grep 一样,它可以-o
选择仅打印匹配的内容,而不是匹配的行),而且还能够打印部分行几次。
pcregrep
是其中之一:
pcregrep -o1 -o2 --om-separator=' ' '(\S+)\s*(?=(\S+))'
在这里,-o2
打印一些本身不匹配的东西,一些只在 a 中匹配的东西展望运算符 ( (?=...)
),因此pcregrep
将从 输出的单词末尾开始继续查找更多匹配项-o1
。
\s
匹配间距(垂直或水平)字符,因此字在这种情况下是非空格字符的序列。
相反,您可以使用awk
:
awk '{for (i=1; i<NF; i++) print $i, $(i+1)}'
为了awk
,字是非空白(水平间距)字符的序列,在某些实现中仅限于 SPC 和 TAB。
如果您想将其line.
视为两个独立的字:line
和,您可以使用支持基于以下模式定义字段.
的 GNU 实现:awk
gawk -v FPAT='[[:alnum:]]+|[[:punct:]]+' '{for (i=1; i<NF; i++) print $i, $(i+1)}'
在哪里字被定义为字母数字字符序列或标点符号字符序列。
答案3
抱歉,这个用途sed, 不是grep:
为了二元组:
sed 'h;:a;s/^ *\([^ ]\+\) \+\([^ ]\+\).*$/\1 \2/p;g;s/^ *[^ ]\+//;h;ta;'
或者也许(替换\+
为\{1,\}
as斯特凡·查泽拉斯的评论指出:
sed -e 'h;:a' -e 's/^ *\([^ ]\{1,\}\) \{1,\}\([^ ]\{1,\}\).*$/\1 \2/p;g;s/^ *[^ ]\{1,\}//;h;ta'
并为卦象:
sed 'h;:a;s/^ *\([^ ]\+\) \+\([^ ]\+\) \+\([^ ]\+\).*$/\1 \2 \3/p;g;s/^ *[^ ]\+//;h;ta;'
对于 Mac 系统sed
:
sed -e 'h;:a' -e 's/^ *\([^ ]\{1,\}\) \{1,\}\([^ ]\{1,\}\) \{1,\}\([^ ]\{1,\}\).*$/\1 \2 \3/p;g;s/^ *[^ ]\{1,\}//;h;ta'
解释:
二元语法作为 sed 脚本:
#!/bin/sed -f
h; # Hold pattern space to hold space
:a; # label for branch
s/^ *\([^ ]\+\) \+\([^ ]\+\).*$/\1 \2/p; # print 1st bigram
g; # restore from hold space
s/^ *[^ ]\+//; # drop 1st monogram
h; # hold pattern space
ta; # branch if last search success
仅当最后一个匹配时才t
标记最后一个(条件分支)。:a
s///
还有麦克的sed
bigram.sed 的版本:
#!/usr/bin/sed -f
h; # Hold pattern space to hold space
# label for branch
:a
s/^ *\([^ ]\{1,\}\) \{1,\}\([^ ]\{1,\}\).*$/\1 \2/p; # print 1st bigram
g; # restore from hold space
s/^ *[^ ]\{1,\}//; # drop 1st monogram
h; # hold pattern space
# branch if last search success
ta