0

假设我有一个输入流,它由分隔成一定数量字段的行组成。我想剪切各个字段,将某个字段(或多个字段)传送到程序(假设每个输入行返回一行)并保持其他字段不变,然后将结果粘贴在一起。我可能可以想象出复杂的解决方案,但应该有一种干净自然的方式来做到这一点。

作为一个具体的例子,假设我有一个程序产生以下形式的行:

$ inputprog
<a> hello world!
<b> hi everyone!
<a> hi!

假设我想将消息以大写形式显示,同时保持第一个字段不变。这是我想象的事情:

$ inputprog | program -d' ' -f2- "tr a-z A-Z"
<a> HELLO WORLD!
<b> HI EVERYONE!
<a> HI!

我正在寻找一种相当干净的方法来近似program. (我对特定于此示例的解决方案不感兴趣。)

在此先感谢您的帮助!

4

1 回答 1

1

awk可以做你想做的事。例如:

$ echo "field1 field2" | awk '{$2 = toupper($2); print;}'
field1 FIELD2

非常接近您想要做的事情。$2 = toupper($2);更改第二个字段,同时print打印出整个(修改的)行。

但是,您在如何定义“字段”方面遇到了问题。在上面的示例中,字段由空格分隔(您可以将字段分隔符更改为任意正则表达式,如下所示:-F'<[a-zA-Z]+>'- 这将被视为字段分隔符)。但是在您的示例中,您似乎将其<a>视为一个领域和hello world!另一个领域。任何程序都只能通过疯狂的猜测来达到你想要的行为。为什么不world!被视为第三个领域?因此,如果您可以通过明确的字段分隔策略获得输入,这awk正是您想要的。

查看http://people.cs.uu.nl/piet/docs/nawk/nawk_92.html(awk 字符串函数)和http://www.pement.org/awk/awk1line.txt(awk 1 liners )等页面) 了解更多信息。

顺便说一句,也可以通过遍历除第一个字段以外的所有字段(NF == 字段数)来使您的上述特定示例起作用:

$ echo "<a> hello world!
<b> hi everyone!
<a> hi" |  
awk '{for(i=2;i<=NF;++i) { $i=toupper($i); }; print;}'
<a> HELLO WORLD!
<b> HI EVERYONE!
<a> HI

即使您对此示例的解决方案不感兴趣。;-)

PS:sed应该也能胜任(http://en.wikipedia.org/wiki/Sed)

于 2011-07-28T08:41:27.903 回答