【问题标题】:Quick Unix command to print non-contiguous lines from a text file?快速 Unix 命令从文本文件中打印不连续的行?
【发布时间】:2015-04-09 16:20:42
【问题描述】:

给定一个名为“people.txt”的文本文件,其中包含:

Anne
Bob
Carl
Daphne
Erwin
Gary
Heather

如何使用 sed 命令或类似的单行命令,它只指定一组不连续的行号,以便将内容过滤到此结果:

Bob
Erwin
Heather

(注意:忽略它们是按字母顺序排列的事实)

请注意,我使用的真实文件有超过 100K 行,所以答案应该考虑效率。

我知道我可以使用:

sed '5q;d' people.txt 

只获得第 5 行(“Erwin”),但是这个参数是否有变体,我可以指定任意行号的列表?

我认为单独使用 sed 是可能的,但即使在阅读完 man sed 之后,我也无法弄清楚这一点。我一直在寻找与此非常接近的其他答案,但几乎所有答案都处理仅获取单行或连续行(一系列行),或者使用更复杂的 bash 脚本;例如,"Quick unix command to display specific lines in the middle of a file?""How can I print specific lines from a file in Unix?"

【问题讨论】:

  • 不连续的行号是什么意思?

标签: shell unix text sed


【解决方案1】:

您可以像这样按数字询问特定的行:

sed -n '1p;5p;7p' my_file

-n 标志表示“默认情况下不打印行”,然后为您想要的每一行指定行号和p(打印)命令。

【讨论】:

  • 啊,这可能是 OP 想要的。在我看到你的答案之前无法破译它:-)
  • 太好了,谢谢!我想这很简单。我今天将对此进行测试,但也许您会立即知道:如果我从 200K 行文件中挑选出 50K 行,这会很好用吗?
  • 很好的答案 - 特别是因为它包括对正在发生的事情的解释。一些sed 功能可能有点难以理解:)。
【解决方案2】:
$ awk -v lines="2 4 7" 'index(" "lines" "," "NR" ")' file  
Bob
Daphne
Heather

$ awk -v lines="3 5" 'index(" "lines" "," "NR" ")' file  
Carl
Erwin

上面linesNR 周围的空白字符是必需的,这样NR 的值9 就不会在lines 包含19 时匹配。

如果您不介意在脚本中硬编码行号,您也可以这样做:

awk 'NR~/^(2|4|7)$/' file

【讨论】:

  • @AdamKatz - 您昨天为删除 index() args 周围的空白字符所做的编辑破坏了上述答案中的脚本,我现在不得不将其改回。请不要编辑我的 awk 答案,因为我通常知道自己在做什么。如果您认为我发布的答案是错误的,请随时给我留言,我很乐意解释或修复它..
  • 很有趣(对此我深表歉意)。当我测试它时,它对我有用。你能解释为什么这些引号是必要的吗?他们所做的只是将空格连接到行的两端。
  • 没问题。您需要在 NR 周围始终有空格以避免错误匹配(NR=9 错误匹配行中的 19=3<blank>19<blank>7,但 NR=<blank>9<blank> 不匹配)并且由于您需要在 NR 周围留空白,因此您需要制作确保行的开头和结尾也总是有空格(NR=<blank>3<blank> 与行=3<blank>19<blank>7 不匹配,但与行=<blank>3<blank>19<blank>7<blank> 匹配)。从给定的输入集产生预期输出的代码总是很容易编写,它是不会为其他复杂的输入产生意外输出的代码。
  • 啊。那为什么不awk -v lines=" 2 4 7 " 'index(lines, " " NR " ")' file呢?此外,使用 mawk 1.3.3 或 gawk 4.1.1,我仍然从 seq 1 999 |awk -v lines='2 4 7' 'index(lines,NR)' 获得 2,4,7。
  • 感谢您的解释。我没有意识到index() 是一个子字符串函数。在这种情况下,我可能会建议更像awk 'NR == 2 || NR == 4 || NR == 7' file,因为它更直接,但使用index() 肯定非常聪明。
【解决方案3】:

动态生成sed程序:

将你想要的行存储在一个数组中:

$ lines=(2 5 7)
$ sed -n "$(printf "%dp;" "${lines[@]}")" file
Bob
Erwin
Heather

或者如果行号在文件中:

$ sed -n "$(sed 's/$/p/' numbers)" file

【讨论】:

    猜你喜欢
    • 2010-09-16
    • 1970-01-01
    • 1970-01-01
    • 2011-01-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多