Bash 在引号内打印时,为什么echo将长行拆分为80个字符?(如何修复它?)

Bash 在引号内打印时,为什么echo将长行拆分为80个字符?(如何修复它?),bash,echo,wc,Bash,Echo,Wc,没有引用的回音。。。一行。好的 $ echo $(ls -1dmb /bin/*) > test $ wc -l test 1 test 与引用相呼应。。。396行。糟糕 $ echo "$(ls -1dmb /bin/*)" > test $ wc -l test 396 test 当使用echo编写文件和扩展长变量时,就会出现问题 为什么会发生这种情况?如何修复它?ls检测到您的stdout不是终端 检查ls-1dmb/bin/*| catvsls-1dmb/bin/*的输出

没有引用的回音。。。一行。好的

$ echo $(ls -1dmb /bin/*) > test
$ wc -l test
1 test
与引用相呼应。。。396行。糟糕

$ echo "$(ls -1dmb /bin/*)" > test
$ wc -l test
396 test
当使用echo编写文件和扩展长变量时,就会出现问题


为什么会发生这种情况?如何修复它?

ls
检测到您的
stdout
不是终端

检查
ls-1dmb/bin/*| cat
vs
ls-1dmb/bin/*
的输出。是ls,正在分割输出

类似地,对于ls--color=auto情况,根据stdout是否为终端,使用
color
选项

使用引号时,
echo
提供了一个参数,该参数包含嵌入的换行符和空格,并按原样回显到文件中

当不使用引号时,
echo
提供多个参数,这些参数由。因此,echo在一行中打印所有这些文件。 但是

如何修复它:

我认为,拆分总是发生在某个文件名的末尾&而不是在文件名之间。因此,以下两个选项之一可能适合您:

ls -1dmb /bin/* | tr '\n' ' ' >test
ls -1dmb /bin/* | tr -d '\n' >test

@anishsane正确地回答了主题问题(即
ls
正在进行包装和移除包装的方法),并涵盖了报价问题,但报价问题对行数差异负责,而不是
ls

这里的问题完全是引用以及命令行、echo和命令替换如何工作的问题

“$(ls…”
的输出是一个字符串,带有嵌入的换行符,通过引号保护它不受shell的影响。将该值交给
echo
,然后
echo
逐字逐句地将其吐出(使用换行符)

$(ls…
的输出是一个不受shell保护的字符串,因此会进行分词和空白规范化。命令替换不能提前终止您的命令行(您不希望在一个包含两个文件的目录中运行
echo first\u file;second\u file
您愿意吗?)换行符作为
echo
参数之间的字分隔符。然后,shell字将结果拆分为空格(包括换行符),并为echo提供一个参数列表,此时
echo
愉快地执行
echo first\u file second\u file…
,您可以猜到,它只输出一行输出

试试看我的意思:

$ c() {
    printf 'argc: %s\n' "$#";
    printf 'argv: %s\n' "$@"
}
$ ls *
a.sh b.sh temp
$ ls -1dmb *
a.sh, b.sh, temp
$ c "$(ls -1dmb *)"
argc: 1
argv: a.sh, b.sh, temp
$ c $(ls -1dmb *)
argc: 3
argv: a.sh,
argv: b.sh,
argv: temp

顺便说一句,这种回声完全没有意义。显然,但这只是一个例子。同样的情况也会发生在很长的变量上,但是这个例子会非常大。实际上,同样的情况不会发生在很长的变量上。回显长变量值不会将行截断为80个字符,
ls
本身就是这样做的。但是,回显长变量值将丢失前导、尾随和嵌入的空格和换行符,因为这是变量扩展和命令替换后的shell字拆分。您是对的。如果手工构造变量,就会发生这种情况,我也不明白这一点。但是我用
ls
构造了我的变量,它被截断了。我想做的是自动编写配置文件,编写用逗号分隔的目录,但回答这个问题不需要知道这些;)。就像我说的,
ls
正在进行换行。shell正在进行换行(和额外的空间)删除。将
echo“foo”
的输出与
echo foo
的输出进行比较,您将看到shell使用空格所做的事情。对长度超过80个字符的带引号的字符串执行同样的操作,您将看不到它在输出中的换行(假设您将其发送到
less
或一个您可以看到它没有正确换行的文件)。
但引号问题是导致行数差异的原因,而不是ls
:嗯,我用另一种方式看待它:正如我们所知
ls
正在将输出拆分为多行。与预期输出的偏差开始于数据流的
ls
阶段,而不是
echo“…”
阶段。(这是我的观点…@anishsane
ls
并没有创建一行输出,而是创建了n行输出(如果它也在包装行,则列出所有文件所需的行数)。Shell分词/
IFS
echo
的行为使不带引号的输出成为一行。此处
-1
ls
的参数完全是误导性的,因为即使输出到终端,它也没有做任何事情。^^^同意。此外,我同意你的上述评论回答了OP的问题,即“为什么引用说明问题而不是引用解决问题”。我要说的是,问题已经由
ls
提出。它通过引用而暴露出来。未被引用时,问题仍然隐藏是的,
-1
确实有误导性。@anishsane帖子主题中的问题是由
ls
介绍的,是的。正文中的问题不是
ls
,而是
echo
和引用。这里真正的问题是,主题和主体在他们提出的问题上不一致此外,关于
-1
是否有意义的混淆对OP毫无帮助。