切割命令(cut command)能够接受换行符作为分隔符吗?

4

我有一个名为foo.txt的文件,包含两行:

foo bar
hello world

我正在尝试使用以下代码输出第二行:
cut -d$'\n' -f2 foo.txt

但它会打印出两行内容。cut 命令能够接受换行符作为分隔符吗?

编辑:为了澄清[...],我可以将"foo bar"捕获为一个变量,将"hello world lorem ipsum"捕获为另一个变量。然后你会用这些变量做什么?请参见https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem/66378#66378。 - kelvin
我认为最好提出另一个问题,并在此处链接它,因为我个人认为我的帖子已适当地回答了原始问题,而编辑中的新信息完全改变了问题。 - kelvin
2
@kelvin 我不应该建议使用命令子 printf,那很愚蠢。尾随的换行符会被剥离。$'\n' 是有效的 bash 语法。你也可以使用 nl=$(printf '\n:'); nl=${nl%:}。我的示例也会被剥离新行,因为它是一条注释:$ cat foo.txt; foo bar hello world $ cut -d$'\n' -f2 foo.txt; hello world 你必须相信我,如果 cut 按照这种方式工作,新行就在你期望的位置。 - dan
1
GNU和Busybox cut都接受换行符作为分隔符。我经常使用它来打印多行范围等。我测试了你的例子,它打印了第二行。你用的是什么操作系统?你可以尝试nl=$(printf '\n:'); nl=${nl%:}; cut -d "$nl" -f 2',并确认你的shell是bash,用echo "$0"命令。我查看了POSIX(2018)标准,但是cut规范在我看来并不是100%清晰。它使用术语“字段”。我能找到的最接近涉及此问题的是:“没有字段分隔符的行将被保持原样,除非指定了-s选项。”。 - dan
1
虽然鼓励对问题进行编辑以提供澄清和/或额外信息,但是不允许进行更改问题的编辑,这些编辑足以使已发布的答案无效,即使您实际上没有提出所需的问题。事实上,共识是任何具有编辑特权的用户都应该撤销此类编辑。我在这里已经这样做了。请注意,这并不会阻止您在任何答案被发布之前完全更改问题。如果您愿意,可以在新问题上发布新问题。 - Makyen
显示剩余2条评论
3个回答

4

背景

cut 命令作用于输入的所有行,因此我认为换行符不能作为分隔符。

引自 POSIX.1-2017 的 cut(1p)

NAME

    cut - cut out selected fields of each line of a file

SYNOPSIS

    cut -b list [-n] [file...]

    cut -c list [file...]

    cut -f list [-d delim] [-s] [file...]

DESCRIPTION

    The cut utility shall cut out bytes (-b option), characters (-c option), or
    character-delimited fields ( -f option) from each line in one or more
    files, concatenate them, and write them to standard output.

例子:

$ printf 'foo bar1\nfoo bar2\n'
foo bar1
foo bar2
$ printf 'foo bar1\nfoo bar2\n' | cut -f 2 -d ' '
bar1
bar2

解决方案

要仅打印输入的第二行,可以使用sed

$ printf 'foo bar1\nfoo bar2\n'
foo bar1
foo bar2
$ printf 'foo bar1\nfoo bar2\n' | sed '2p;d'
foo bar2

0

不太清楚你想要什么,但这是在空行上分割并使用awk折叠其他内容:

awk 'BEGIN {RS=""} {gsub("\n",""); print}'

0

这可能不是非常优雅的解决方案,但我经常只使用headtail,因为它们通常在速度上优于sedawk

#!/bin/sh

input='test0\ntest1\ntest2\ntest3\ntest4\ntest5'


echo -e "$input" | head --lines 3
# test0
# test1
# test2

echo -e "$input" | tail --lines 3
# test3
# test4
# test5

get_index() {
    echo -e "$1" |
        head --lines "$(( $2 + 1 ))" |
        tail --lines "1"
}

get_index "$input" "0"
# test0

get_index "$input" "4"
# test4

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接