【问题标题】:Split bash string by newline characters用换行符分割 bash 字符串
【发布时间】:2013-11-15 07:43:49
【问题描述】:

我找到了this

我正在尝试这个:

x='some
   thing'

y=(${x//\n/})

我没有运气,我认为它可以使用双反斜杠:

y=(${x//\\n/})

但它没有。

为了测试我没有得到我想要的东西:

echo ${y[1]}

获取:

some
thing

我想成为什么样的人:

some

我希望 y 成为数组 [some, thing]。我该怎么做?

【问题讨论】:

  • 请注意,一旦您解决了换行问题,some 将位于 ${y[0]},而不是 ${y[1]}
  • @juanpastas 仅供参考,链接到的解决方案已更新,包括当您的输入有空格时如何在换行符上拆分stackoverflow.com/a/5257398/52074

标签: string bash shell


【解决方案1】:

另一种方式:

x=$'Some\nstring'
readarray -t y <<<"$x"

或者,如果您没有 bash 4,则使用 bash 3.2 等效项:

IFS=$'\n' read -rd '' -a y <<<"$x"

您也可以按照您最初尝试使用的方式进行操作:

y=(${x//$'\n'/ })

但是,如果您的字符串已经包含空格,例如'line 1\nline 2',这将无法正常工作。要使其工作,您需要在解析之前限制单词分隔符:

IFS=$'\n' y=(${x//$'\n'/ })

...然后,由于您正在更改分隔符,因此您无需再将\n 转换为space,因此您可以将其简化为:

IFS=$'\n' y=($x)

此方法将起作用除非$x 包含匹配的通配符模式(例如“*”) - 在这种情况下,它将被匹配的文件名替换。 read/readarray 方法需要更新的 bash 版本,但适用于所有情况。

【讨论】:

  • 在扩展模式中匹配\n\\n 的实例不起作用;相反,您必须拼接 \n literal: echo ${x//$'\n'/ }.
  • readarray 方法实际上是最健壮的 方法,因为($x) 仍然受制于通配符:如果有任何一行恰好是一个有效的,single-token globbing 模式(例如,*),如果文件恰好匹配,它将被扩展。但是,readarray 需要 bash 4;这是 bash 3.2 的等价物(对于那些在 OS X 上的):IFS=$'\n' read -rd '' -a y &lt;&lt;&lt;"$x"。由于您的帖子越来越受欢迎,您介意添加这些发现吗?
  • 使用-treadarray - 即readarray -t y &lt;&lt;&lt;"$x" - 防止终止的\n 成为数组元素的一部分。
  • @mklement0:再次感谢!
  • 另外,请注意read 命令的返回码是1(例如,失败),因为在读取的流的末尾看不到分隔符。正确的做法是:IFS=$'\n' read -d '' -ra y &lt; &lt;(printf '%s;\0' "$x"),如this answer中提到的。请注意,对于类似空格的字符(即空格、换行符或制表符),连续的分隔符将被视为唯一的分隔符。所以read 方法与readarray/mapfile 换行方法略有不同。
【解决方案2】:

如果你想要的只是第一个换行符之前的文本,还有另一种方法:

x='some
thing'

y=${x%$'\n'*}

在那之后y 将包含some 并且没有其他内容(没有换行符)。

这里发生了什么?

我们执行parameter expansion substring removal (${PARAMETER%PATTERN}) 以获取到第一个ANSI C line feed ($'\n') 的最短匹配,并删除后面的所有内容 (*)。

【讨论】:

    猜你喜欢
    • 2022-07-06
    • 1970-01-01
    • 2012-07-07
    • 2013-02-15
    • 2014-09-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-25
    相关资源
    最近更新 更多