用换行符分割bash字符串

jua*_*tas 52 string bash shell

我找到了这个.

我正在尝试这个:

x='some
   thing'

y=(${x//\n/})
Run Code Online (Sandbox Code Playgroud)

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

y=(${x//\\n/})
Run Code Online (Sandbox Code Playgroud)

但事实并非如此.

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

echo ${y[1]}
Run Code Online (Sandbox Code Playgroud)

获得:

some
thing
Run Code Online (Sandbox Code Playgroud)

我想成为:

some
Run Code Online (Sandbox Code Playgroud)

我想y成为一个阵列[some, thing].我怎样才能做到这一点?

Sir*_*hos 89

其他方式:

x=$'Some\nstring'
readarray -t y <<<"$x"
Run Code Online (Sandbox Code Playgroud)

或者,如果你没有bash 4,则bash 3.2等效:

IFS=$'\n' read -rd '' -a y <<<"$x"
Run Code Online (Sandbox Code Playgroud)

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

y=(${x//$'\n'/ })
Run Code Online (Sandbox Code Playgroud)

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

IFS=$'\n' y=(${x//$'\n'/ })
Run Code Online (Sandbox Code Playgroud)

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

IFS=$'\n' y=($x)
Run Code Online (Sandbox Code Playgroud)

除非 $x包含匹配的globbing模式(例如" *"),否则此方法将起作用- 在这种情况下,它将被匹配的文件名替换.该read/ readarray方法需要新的bash的版本,但在所有的情况下工作.

  • 另外,请注意您的“read”命令的返回码是“1”(例如,失败),因为在读取流的末尾看不到分隔符。正确的方法是:`IFS=$'\n' read -d '' -ra y &lt; &lt;(printf '%s;\0' "$x")`,如[this answer](http:// /stackoverflow.com/questions/918886/how-do-i-split-a-string-on-a-delimiter-in-bash/24426608#24426608)。请注意,对于类似空格的字符(即空格、换行符或制表符),连续的分隔符将被视为唯一的分隔符。因此,`read` 方法与用于换行的 `readarray`/`mapfile` 方法略有不同。 (4认同)
  • `readarray`方法实际上是*最强大的*方法,因为`($ x)`仍然受到globbing*的影响:如果任何一行恰好是一个有效的*单一令牌*通配模式(例如,`*`),如果文件恰好匹配,它将被扩展.`readarray`需要bash*4*; 这里是bash 3.2等价物(适用于OS X上的那些):`IFS = $'\n'读取-rd''-ay <<<"$ x"`.由于您的帖子越来越有吸引力,您是否介意添加这些发现? (2认同)
  • 将`-t`与`readarray`一起使用 - 即`readarray -ty <<<"$ x"` - 以防止终止`\n`成为数组元素的一部分. (2认同)

Fle*_*der 9

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

x='some
thing'

y=${x%$'\n'*}
Run Code Online (Sandbox Code Playgroud)

之后y将不包含some任何其他内容(无换行)。

这里发生了什么?

我们对第一个ANSI C 换行符( ) 之前的最短匹配执行参数扩展子字符串删除( ),并删除后面的所有内容 ( )。${PARAMETER%PATTERN}$'\n'*