如何在Bash中编写奇特的多线括号扩展?

时间:2016-06-14 14:21:56

标签: bash indentation curly-braces brace-expansion

我正在处理这样的一行:

mkdir -p "$DEST_ROOT_PATH/"{"$DEST_DIR1","$DEST_DIR2", ..., "$DEST_DIRN"}

这条线很长。我想剪切它,使其宽度适合80列线。我试图用反斜杠逃避结束,但空间对齐打破了扩展:

$ echo "ha"{a,b,\
>           c}
ha{a,b, c}

4 个答案:

答案 0 :(得分:7)

你可以使用这个恶心的黑客。

echo "ha"{a,b,\
> `      `c}

它会打开一个没有任何内容的子shell,但会在扩展之前进行处理,因此扩展只会看到一个空白区域

答案 1 :(得分:6)

这是正常行为。从Bash参考手册:

  

3.5.1 Brace expansion

     

支撑扩展是任意字符串可能的机制   产生。这种机制类似于文件名扩展(参见   文件名扩展),但生成的文件名不需要存在。   要扩展的模式采用可选前导码的形式,后跟一系列以逗号分隔的字符串或序列   一对括号之间的表达,后跟一个可选的   后记即可。前导码以包含在其中的每个字符串为前缀   然后将括号和后记附加到每个结果上   字符串,从左向右扩展。

支撑扩展不允许在\和下一行中的下一个元素之间放置元素之间的空格。

为什么?因为它在处理时被删除了:

  

3.1.2.1 Escape Character

     

未引用的反斜杠'\'是Bash转义字符。它保留   随后的下一个字符的字面值,用   换行例外。如果出现\ newline对,则反斜杠   本身没有引用,\ newline被视为一个续行   (也就是说,它会从输入流中有效地删除   忽略)。

所以当你说

something + \ + <new line> + another_thing

Bash将其转换为

something + another_thing

那你能做什么?

添加一个反斜杠,然后从下一行的开头开始写:

mkdir -p "$DEST_ROOT_PATH/"{"$DEST_DIR1",\
"$DEST_DIR2",\
...,\
"$DEST_DIRN"}

一些例子

当你说:

$ echo "ha"{a,b\
>    c}
ha{a,b c}

然后向上移动箭头,你会看到这是执行的命令:

$ echo "ha"{a,b   c}

所以只说:

$ echo "ha"{a,b\
> c}
haa habc

你向上移动时会看到这个:

$ echo "ha"{a,b,c}

另一个例子:

$ cat touch_files.sh
touch X{1,\
2,3}
$ bash touch_files.sh
$ ls X*
X1 X2 X3

答案 2 :(得分:2)

因此我接受了@ 123的回答,这是我选择的那个:

mkdir -p "$DEST_ROOT_PATH/"{"$DEST_DIR1","$DEST_DIR2"}
mkdir -p "$DEST_ROOT_PATH/"{"$DEST_DIR3","$DEST_DIR4"}

这里没有很多目的地目录,所以我认为它在花哨恶心的黑客和打破缩进的令人沮丧的反斜杠之间取得了很好的平衡。

答案 3 :(得分:1)

我会这样做(虽然它只解决了你创建多个目录的特定任务,但没有回答标题中所述的问题):

for d in \
      "$DEST_DIR1" \
      "$DEST_DIR2" \
       ...         \
      "$DEST_DIRn" \
      ;
do
    mkdir -p "$DEST_ROOT_PATH/$d"
done

这种方法的优点是保持列表更容易。

一般来说,当你发现它开始造成不便时,你应该停止坚持使用语法糖。