bash Bash中没有空格的字符串连接
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/33226264/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
String concatenation without spaces in Bash
提问by Teofrostus
I'm trying to write a simple bash script to count the number of files in a directory, and then add a new file with name file<#files> to the end of the directory. My current attempt is:
我正在尝试编写一个简单的 bash 脚本来计算目录中的文件数,然后在目录末尾添加一个名为 file<#files> 的新文件。我目前的尝试是:
name="out"
num=$(ls -l|wc -l)
echo foo > "${name}${num}"
However, this gives me a bunch of spaces, resulting in the filename out 12
. Why do the spaces appear, and how do I concatenate these strings without creating spaces?
但是,这给了我一堆空格,导致 filename out 12
。为什么会出现空格,以及如何在不创建空格的情况下连接这些字符串?
回答by mklement0
On OS X (and BSD-like systems in general), wc -l
left-space-pads the number to 8 characters, e.g., _______7
(_
representing a space here for technical reasons).
在OS X(以及一般的 BSD 类系统)上,wc -l
左空格将数字填充为 8 个字符,例如,_______7
(_
出于技术原因,此处表示一个空格)。
(If you use wc
's output unquotedwith echo
- e.g., echo $(wc -l <<<'dummy')
, you will notsee the padding, because the shell will "eat" the leading spaces; if you double-quotethe command substitution, you'll see them: echo "$(wc -l <<<'dummy')"
(如果你使用wc
的输出不带引号用echo
-例如 echo $(wc -l <<<'dummy')
,你将不会看到填充,因为shell会‘吃’的前导空格;如果双引号的命令替换,你会看到他们: echo "$(wc -l <<<'dummy')"
That said, you're better off using neither ls
nor wc
- for both reasons of robustness and performance; use globbingto capture all filenames in an array and use that array's element countinstead:
也就是说,出于健壮性和性能的原因,您最好ls
不要使用也不使用wc
-;使用globbing捕获数组中的所有文件名,并使用该数组的元素计数:
name='out'
files=( * ) # collect all filenames in array
echo foo > "${name}${#files[@]}" # use array-element count
Note: By default, *
will notinclude hiddenitems, just like the OP's ls
command (because it doesn't include -A
or -a
).
Use shopt -s dotglob
to include hidden items too.
Also, if there happen to be no matching items at all, Bash will return the pattern as-is, i.e., *
; to have Bash return the empty stringinstead, use shopt -s nullglob
.
注意:默认情况下,*
将不包括隐藏的物品,就像OP的ls
命令(因为它不包括-A
或-a
)。
也shopt -s dotglob
用于包含隐藏的项目。
此外,如果碰巧根本没有匹配项,Bash 将按原样返回模式,即*
; 要让 Bash 返回空字符串,请使用shopt -s nullglob
.
Generally, if you do find yourself needing to trim leading and trailing whitespacefrom command output and/or a Bash variable:
通常,如果您发现自己需要从命令输出和/或 Bash 变量中修剪前导和尾随空格:
To trim a value stored in a Bash variable, use
read
:# Single-line value: val=' a b ' read -r val <<<"$val" # $val now contains 'a b' # Multi-line value: # Note: Trims leading and trailing whitespace including newlines, but # preserves *any* interior whitespace, including empty and all-whitespace lines. val=$'\n \t one\n \ntwo\n \n' read -r -d '' val <<<"$val" # $val now contains $'one\n \ntwo'
To trim command outputas part of a pipeline or lines from stdin/ a file:
If the value to trim has either no interiorwhitespace oryou want to ensure / don't mind that interior whitespace is normalizedto a single spaceeach, pipe to
xargs
(this works, becausexargs
, after parsing the input into words, passes them to theecho
utility by default - without shell involvement); the result is always a singleoutput line; caveat:xargs
removes embedded quotes and\
instances, unless you\
-escape them:val=$(ls | wc -l | xargs) # $val now contains trimmed count
If preserving line-interiorwhitespace as-is matters, use
sed
; note that - unlikeread -r d ''
above - this is a LINE-based solution, so the number of input lines will be preserved, including leading and trailing empty or all-whitespace lines, with all-whitespace lines trimmed to emptyones(assumes GNUSed or BSDSed):echo $'\nfoo \n \n bar \n' | sed -E 's/^[[:blank:]]+|[[:blank:]]+$//g' # -> $'\nfoo\n\nbar'
要修剪存储在Bash 变量中的值,请使用
read
:# Single-line value: val=' a b ' read -r val <<<"$val" # $val now contains 'a b' # Multi-line value: # Note: Trims leading and trailing whitespace including newlines, but # preserves *any* interior whitespace, including empty and all-whitespace lines. val=$'\n \t one\n \ntwo\n \n' read -r -d '' val <<<"$val" # $val now contains $'one\n \ntwo'
要修剪命令输出作为管道的一部分或者从线标准输入/一个文件:
如果要修剪的值没有内部空格,或者您想确保/不介意内部空格被规范化为每个空格,则管道到
xargs
(这是有效的,因为xargs
在将输入解析为单词后,将它们传递给echo
默认情况下的实用程序 - 没有外壳参与);结果始终是单个输出行;警告:xargs
删除嵌入的引号和\
实例,除非你\
-escape 它们:val=$(ls | wc -l | xargs) # $val now contains trimmed count
如果按原样保留行内部空白很重要,请使用
sed
; 注意, -不同于read -r d ''
以上-这是一个基于LINE-溶液,所以输入线的数量将被保留,包括前缘和后空或全部空白线,修剪到所有空白行空那些(假定GNU桑达或BSDsed):echo $'\nfoo \n \n bar \n' | sed -E 's/^[[:blank:]]+|[[:blank:]]+$//g' # -> $'\nfoo\n\nbar'
Simplified scenario: Remove ALL whitespacefrom a value, using
tr
:single-line / per-line:
tr -d '[:blank:]' <<<$' a b c \n foo ' # -> $'abc\nfoo\n'
globally, including newlines:
tr -d '[:space:]' <<<$' a b c \n foo ' # -> 'abcfoo'
简化场景:从值中删除所有空格,使用
tr
:单行/每行:
tr -d '[:blank:]' <<<$' a b c \n foo ' # -> $'abc\nfoo\n'
全局,包括换行符:
tr -d '[:space:]' <<<$' a b c \n foo ' # -> 'abcfoo'
回答by William Dye
http://mywiki.wooledge.org/BashFAQ/004describes how to concisely count the number of items in a directory. For example, the following code might do what you want:
http://mywiki.wooledge.org/BashFAQ/004描述了如何简洁地计算目录中的项目数。例如,以下代码可能会执行您想要的操作:
shopt -s nullglob dotglob
items=(*)
touch "file${#items[@]}"
echo "${#items[@]} items found, created new file: file${#items}"
Please note, however, that this count includes subdirectories and symlinks, not just files. In your description you asked for a count of files, though in your code example you seem to also want subdirectories and such. If you only want files, then the above example will have to be modified, perhaps with something like 'find . -type f'.
但是请注意,此计数包括子目录和符号链接,而不仅仅是文件。在您的描述中,您要求提供文件数,但在您的代码示例中,您似乎还需要子目录等。如果您只需要文件,则必须修改上面的示例,可能使用诸如 'find 之类的内容。- 类型 f'。
回答by ergonaut
try this:
尝试这个:
#!/bin/sh
name="out"
num=$(ls -l | wc -l | sed -e 's/ //g')
echo $num
which should strip out the beginning whitespace.
这应该去掉开头的空格。