简体   繁体   English

Bash中没有空格的字符串连接

[英]String concatenation without spaces in Bash

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. 我正在尝试编写一个简单的bash脚本来计算目录中的文件数,然后将名为file <#files>的新文件添加到目录的末尾。 My current attempt is: 我目前的尝试是:

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 . 但是,这给了我一堆空格,导致文件名out 12 Why do the spaces appear, and how do I concatenate these strings without creating spaces? 为什么会出现空格,如何在不创建空格的情况下连接这些字符串?

On OS X (and BSD-like systems in general) , wc -l left-space-pads the number to 8 characters , eg, _______7 ( _ representing a space here for technical reasons). OS X(以及一般类似BSD的系统)上wc -l左空间将数字 _______7 到8个字符 ,例如_______7 (由于技术原因, _表示空格)。

(If you use wc 's output unquoted with echo - eg, echo $(wc -l <<<'dummy') , you will not see the padding, because the shell will "eat" the leading spaces; if you double-quote the 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 ; 也就是说, 出于稳健性和性能的原因你最好不要使用lswc use globbing to capture all filenames in an array and use that array's element count instead: 使用globbing捕获数组中的所有文件名,并使用该数组的元素计数

name='out'
files=( * ) # collect all filenames in array

echo foo > "${name}${#files[@]}" # use array-element count

Note: By default, * will not include hidden items, just like the OP's ls command (because it doesn't include -A or -a ). 注意:默认情况下, * 不会包含隐藏项,就像OP的ls命令一样(因为它不包括-A-a )。
Use shopt -s dotglob to include hidden items too. 使用shopt -s dotglob可以包含隐藏的项目。
Also, if there happen to be no matching items at all, Bash will return the pattern as-is , ie, * ; 此外,如果根本没有匹配的项目,Bash将按原样返回模式,即* ; to have Bash return the empty string instead, use shopt -s nullglob . 要让Bash返回空字符串 ,请使用shopt -s nullglob


Generally , if you do find yourself needing to trim leading and trailing whitespace from command output and/or a Bash variable : 通常 ,如果您确实发现需要从命令输出和/或Bash变量修剪前导和尾随空格

  • To trim a value stored in a Bash variable , use read : 修剪存储在Bash变量中的 ,请使用read

      # Single-line value: val=' ab ' read -r val <<<"$val" # $val now contains 'ab' # 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 output as part of a pipeline or lines from stdin / a file : 要将命令输出作为管道的一部分或stdin / a 文件中的 修剪

    • If the value to trim has either no interior whitespace or you want to ensure / don't mind that interior whitespace is normalized to a single space each , pipe to xargs (this works, because xargs , after parsing the input into words, passes them to the echo utility by default - without shell involvement); 如果要修剪的值没有内部空白, 或者你想要确保/不介意内部空白每个规范化为一个空格 ,请管道到xargs (这是有效的,因为xargs在将输入解析为单词后传递它们默认情况下为echo实用程序 - 没有shell参与); the result is always a single output line ; 结果始终是一个单一的输出线 ; caveat : xargs removes embedded quotes and \\ instances, unless you \\ -escape them: 警告xargs去除嵌入引号和\\情况下,除非你\\ -escape它们:

       val=$(ls | wc -l | xargs) # $val now contains trimmed count 
    • If preserving line-interior whitespace as-is matters , use sed ; 如果保留线内部空白非常重要 ,请使用sed ; note that - unlike read -rd '' 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 empty ones (assumes GNU Sed or BSD Sed): 请注意 - 与上面的read -rd ''不同 - 这是一个基于LINE的解决方案,因此输入行的数量将被保留 ,包括前导和尾随空行或全空行, 所有空白行都被修剪为 (假设GNU Sed或BSD Sed):

       echo $'\\nfoo \\n \\n bar \\n' | sed -E 's/^[[:blank:]]+|[[:blank:]]+$//g' # -> $'\\nfoo\\n\\nbar' 

  • Simplified scenario: Remove ALL whitespace from a value, using tr : 简化方案:使用tr从值中删除所有空格

    • single-line / per-line : 单行/每行

       tr -d '[:blank:]' <<<$' abc \\n foo ' # -> $'abc\\nfoo\\n' 
    • globally, including newlines : 全球,包括换行

       tr -d '[:space:]' <<<$' abc \\n foo ' # -> 'abcfoo' 

http://mywiki.wooledge.org/BashFAQ/004 describes how to concisely count the number of items in a directory. http://mywiki.wooledge.org/BashFAQ/004介绍了如何简明地计算目录中的项目数。 For example, the following code might do what you want: 例如,以下代码可能会执行您想要的操作:

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 . 如果你只想要文件,那么上面的例子将不得不被修改,也许是像'find一样。 -type f'. -type f'。

try this: 尝试这个:

#!/bin/sh
name="out"
num=$(ls -l | wc -l | sed -e 's/ //g')
echo $num

which should strip out the beginning whitespace. 它应该删除开头的空白。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM