bash变量中的新行


9

我正在尝试在bash变量中存储多行,但是它似乎不起作用。

例如,如果我/bin每行列出一个文件并将其存储在中$LS,那么我$LS将以stdin的形式传递给wc,则该文件始终返回1:

$ ls -1 /bin | wc -l
134
$ LS=$(ls -1 /bin); wc -l <<< $LS
1

如果尝试输出到屏幕,则会得到各种结果:将echo所有行打印在一行上,而printf仅打印第一行:

#!/bin/bash
LS=$(ls -1 /bin)
echo $LS
printf $LS

那么,bash变量可以包含多行吗?

Answers:


15

您需要将其双引号(在大多数情况下,您应将 变量双引号):

echo "$LS"

但是不要使用echo来打印变量内容,而应该使用printf

printf '%s\n' "$LS"

1
只是为了更好地说明整体答案:printf希望格式字符串是其第一个参数,这就是为什么他们没有看到期望的结果。如果他们想在printf的输出中看到换行符,请在空格之间进行任意分割,printf "%s\n" $LS可以这样做。
杰夫·谢勒

%LS应该是$ LS,顺便说一句(我不能做这么短的编辑)
Jeff Schaller

谢谢!当然,它也可以wc与其他命令一起使用:wc -l <<< "$LS"
Wizard79,2015年

1
@JeffSchaller:不,在这种情况下,您不应该取消对变量的引用,仅printf '%s\n' "$LS"当您想查看换行符时使用。键入错误,将其修复!
cuonglm

为什么不使用echo打印变量?
2015年

9

换行符在变量中。LS=$(ls -1)将变量设置LS为的输出ls -1ls顺便说一下,其输出与相同,除非输出到终端),然后减去尾随的换行符。

问题在于,当您打印出该值时,您正在删除换行符。在shell脚本中,$LS并不表示“变量的值LS”,而是表示“取的值LS,根据其将其拆分为单词IFS并将每个单词解释为glob模式”。要获取的值LS,您需要编写"$LS",或更一般地说,将其放在$LS双引号之间。

echo "$LS"打印的值LS,在某些解释反斜杠字符的外壳程序中,以及以开头的一些值除外-

printf "$LS"LS只要不包含任何百分比或反斜杠字符并且(对于大多数实现)不以开头,就打印的值-

要打印LS精确值,请使用printf %s "$LS"。如果您想在末尾使用换行符,请使用printf '%s\n' "$LS"

请注意,$(ls)通常不是当前目录中的文件列表。仅当您具有足够的驯服文件名时,这才起作用。要获取文件名列表(点文件除外),您需要使用通配符:*。结果是一个字符串列表,而不是一个字符串,因此您不能将其分配给一个字符串变量。您可以files=(*)在支持它们的shell中使用数组变量(ksh93,bash,zsh)。

有关更多信息,请参见为什么我的shell脚本在空白或其他特殊字符上感到窒息?


printf“ $ LS”也将屈服于反斜杠字符解析,类似于echo
cnst 2015年

0

之前所提

printf '%s\n' "$LS"

是唯一正确的解决方案。

让我证明其他建议的解决方案(echoprintf都不能正常使用):

$ mkdir t
$ cd t
$ touch \\n
$ LS=$(ls -l)
$ echo "$LS"
total 0
-rw-r--r--  1 domain  domain  0 Nov  5 06:12

$ printf "$LS\n"
total 0
-rw-r--r--  1 domain  domain  0 Nov  5 06:12

$ printf '%s\n' "$LS"
total 0
-rw-r--r--  1 domain  domain  0 Nov  5 06:12 \n
$ ls -l
total 0
-rw-r--r--  1 domain  domain  0 Nov  5 06:12 \n
$ rm \\n
$ cd ..
$ rmdir t
$

(也可以使用V=$(printf 'line0:\\n\\n\nline1.\n') printf '%s\n' "$V"和进行测试。)

\n在文件名中可能并不常见,将其存储git diff到变量中,遇到字面\n量的机会会大大增加。


请注意,ksh并且zsh也支持print -r -- "$LS"zsh也具有echo -E - $LScsh具有echo $LS:q尽管这不输出换行符如果$ LS是空的,并得到一个多值转换成首位$ LS是在csh相当棘手。
斯特凡Chazelas
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.