Unix 终端 - 如何打印一行中的每个二元/三元?

Unix 终端 - 如何打印一行中的每个二元/三元?

如何使用 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 '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标记最后一个(条件分支)。:as///

还有麦克的sedbigram.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

相关内容