我想知道相当于
grep -oE '[^ ]+$' pathname
awk 或 sed。如果有人可以回答并解释那就太好了。谢谢。
答案1
awk
是 的超集grep
,因此您也可以在以下位置使用该grep
模式awk
:
awk '{match($0, "[^ ]+$"); if (RSTART > 0) print substr($0, RSTART, RLENGTH)}'
答案2
让我们grep
首先回顾一下您的命令的作用:
- 告诉只
-o
输出grep
匹配的部分而不是整行 - 该
-E
标志允许使用扩展正则表达式 '[^ ]+$'
将匹配在行末尾重复一次或多次的任何非空格字符 - 基本上是行末尾的一个单词。
测试运行:
$ cat input.txt
to be or not to be
that is the question
$ grep -oE '[^ ]+$' input.txt
be
question
现在,我们怎样才能在 中做同样的事情awk
呢?考虑到awk
默认情况下对每行以空格分隔的条目(我们称之为单词 -awk
称之为字段)进行操作,这很容易。因此,我们可以$NF
使用 awk 进行打印 - 获取NF
字段数量的变量并将其视为引用特定字段。但请注意,该grep
命令只会匹配非空行,即那里至少有一个单词。因此,我们需要一个条件awk
- 仅对NF
字段数大于零的行进行操作。
awk 'NF{print $NF}' input.txt
应该指出的是,GNU awk 至少支持扩展的正则表达式(我对其他人不太熟悉,所以不会对其他人提出要求)。因此,我们还可以根据 cuonglm 的答案写出一个变体:
$ awk '{if(match($0,/[^ ]+$/)) print $NF}' input.txt
be
question
使用 GNUsed
也可以使用扩展的正则表达式 - 这需要-r
标志,但不能简单地使用相同的正则表达式。需要使用反向引用\1
。
$ cat input.txt
to be or not to be
that is the question
blah
$ sed -r -e 's/^.* ([^ ]+)$/\1/' input.txt
be
question
blah
使用基本正则表达式可以获得所需的结果,如下所示:
$ cat input.txt
to be or not to be
that is the question
blah
$ sed 's/^.* \([^ ].*\)$/\1/' input.txt
be
question
blah
欲了解更多信息,请参阅这些帖子:
答案3
在 awk 中:
awk 'NF>0 {print $NF}' ## fails with end of line spaces; \thnaks{cuonglm}
awk '/[^ ]$/ {print $NF}' ## fails with tabs in lasts field; \thanks{Terdon}
awk -F ' +' '$NF {print $NF}' ## too tricky
awk 'match($0,/[^ ]+$/,a){print a[0]}' ## follows def. of grep -o
在 sed 中:
sed -nr 's/(|.* )([^ ]+)$/\2/p'
\谢谢{cuonglm}
以及(为什么不呢?)在 Perl 中
perl -nlE '/([^ ]+)$/ and say $1'
答案4
这与您尝试使用 grep 执行的操作等效于 sed:
# there is a space n a tab in the [...]
sed -ne '/[^ ]$/s/.*[ ]//p'
# this makes the code intent visually unambiguous
TAB=`echo 'x' | tr 'x' '\011'`; # tab
SPC=`echo 'x' | tr 'x' '\040'`; # space
h="[$SPC$TAB]"; # whitespace
S="[^$TAB$SPC]"; # nonwhitespace
sed -ne "/$S\$/s/.*$h//p"
sed -ne "s/.*$h\($S$S*\)\$/\1/p"