不剪时应该使用什么?


19

我有一个cities像这样的文件:

[1598] San Diego, US (inactive)
[4517] St Louis, US (inactive)
[6346] Orlando, US (inactive)

我想删掉城市名称,以便:

San Diego
St Louis
Orlando

这是我能想到的最好的方法:

cut -d ',' -f1 cities | cut -d ']' -f2

但这仍然使我在名字之前留了一个空格。有没有cut类似的命令可以接受几个字符的分隔符,以便继续使用]


1
tr对于删除不需要的字符很有用。
LawrenceC

如果您尝试使用人们的答案中的代码,则会看到三个不同的输出。这表明您的问题不是100%清楚。“剪出”是否意味着删除或选择?您是否想要(inactive)状态?请提供样本输出。
Mikel

@Mikel-考虑到我习惯于cut删除内容,您可以看到我失败示例的意图,因此在上下文中应该很清楚。我将提供样本,以便进一步清除。:)
Kit Sunde

不,不是。我将您的问题中的一个句子更改为“仅打印城市名称”,因为您不清楚我对“切”一词的使用。我的更改正确吗?
Mikel

1
@Kit Sunde:使用示例输出,这当然是可以理解的。标题很可爱。“删节”让我想到了当您按Ctrl + X时会发生什么,这就是为什么我建议进行更改,但这是您的问题。当仅仅是一个简单的分歧时,拒绝投票就是愚蠢的。
Mikel

Answers:


15

Awk(也请查看Awk Info)对此类问题很满意。尝试:

awk -F'[],] *' '{print $2}' cities

这将字段分隔符定义-F[],] *-表示出现一个方括号或逗号,后跟零或任意数量的空格。当然,您可以更改它以适合任何要求。阅读正则表达式。

分割线后,就可以对分割结果进行所需的操作。在这里,我决定仅使用来打印第二个字段print $2。请注意,在awk指令周围使用单引号很重要,否则$ 2将被shell替换。


2
]不是尖括号。尖括号为<>[]是“方括号”,也就是“方括号”。
cjm 2011年

我认为您需要逃脱最后的括号,除非我确实需要继续阅读正则表达式。
Kit Sunde

@cjm-也许他是德国人:news.ycombinator.com/item?id=1181243 :)
Kit Sunde

1
@cjm,抱歉,我的意思是说方括号,键入得太快了。@Kit,我不是德国人。您不想转义内部的右括号(这没有用),但是它必须是范围内的第一个字符。
asoundmove 2011年

12

您可以cut将管道中的最后一个修改为:

cut -d ' ' -f2-

上面的意思是字段分隔符是空格,我们要从第二个开始选择所有字段。完整的序列变为:

cut -d ',' -f1 cities | cut -d ' ' -f2-

12

对于更复杂的解析,您应该使用sed(1)

sed -e 's/\[[0-9]\+\] \([^,]\+\),.*/\1/' cities

或使用-r来简化正则表达式,如pepoluan所建议:

sed -re 's/\[[0-9]+\] ([^,]+),.*/\1/' cities

2
+1。您还可以使用-r防止转义高级regex字符,从而大大简化了regex模式
pepoluan 2011年

0

当事情对于sed和grep变得太困难时,我通常会使用Perl。

您可以用多种方法在Perl中编写它。例如,您可能希望它速度很快,或者您可能希望它处理输入中的一些意料之外的问题(例如,预期有两个空格)。

一种明显的方式(假设id是数字,城市是字母,状态是字母):

while (<>) {
    if (/^\[\d+\] (\w+(?: \w+)*), \w+ \(\w*\)$/) {
        my $city = $1;
        print "$city\n";
    }
}

或更慢但更宽松(执行更多回溯):

while (<>) {
    if (/^.*\]\s+(.*),.*$/) {
        my $city = $1;
        print "$city\n";
    }
}

或更快(字段在出现右括号时停止):

while (<>) {
    if (/^\[[^]]*\] ([^,]*), \S+ \([^)]*\)$/) {
        my $city = $1;
        print "$city\n";
    }
}

您可以从命令行而不是脚本中使用该-n选项,该选项基本上会添加while (<>) { BLOCK }循环:

perl -ne '/^\[[^]]*\] ([^,]*), \S+ \([^)]*\)$/ and print $1, "\n";' cities

或者如果您想使用法类似于cut,则可以使用-F与awk的-F选项类似的选项,例如:

perl -a -n -F'/[],]\s+/' -e 'print $F[1], "\n"' cities

显然,这种方式假定没有字段将包含任何定界符。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.