如何在Bash中编写花式缩进的多行大括号扩展?

3

我正在处理这样一行代码:

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

这一行比较长,我想将其切割成适合80列的宽度。我尝试使用反斜杠转义换行符,但是空格对齐会破坏扩展:

$ echo "ha"{a,b,\
>           c}
ha{a,b, c}
4个回答

7
你可以使用这种令人讨厌的技巧。
echo "ha"{a,b,\
> `      `c}

它打开一个没有任何内容的子shell,在扩展之前被处理,因此扩展只会看到一个空格。


3
可能会让人感到恶心,但它相当聪明! - fedorqui
1
谢谢你,已接受。令人讨厌但已接受。现在我在面临一个可怕的选择,不知道是否会使用它。 :) - Amessihel

6
这是正常的行为。根据Bash参考手册:
花括号扩展是一种生成任意字符串的机制。该机制类似于文件名扩展(请参阅文件名扩展),但所生成的文件名不需要存在。要进行花括号扩展的模式采用可选前导部分,后跟一系列逗号分隔的字符串或在一对花括号之间的序列表达式,然后是可选的附言。前导部分加在花括号中包含的每个字符串之前,然后将后缀附加到每个结果字符串上,从左到右扩展。
花括号扩展不允许在放置在反斜杠和下一行中的下一个元素之间存在空格。
为什么呢?因为在处理时会将其删除。

3.1.2.1 转义字符

非引用状态下的反斜杠‘\’是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
我认为他们已经知道了。但是空格对齐会破坏扩展: - 123
1
感谢@fedorqui。我猜到了发生了什么(只需要一个好的技巧),但引用官方文档以供进一步阅读是很有用的。 - Amessihel
@Amessihel 很高兴这个对你有用。一开始我理解你的问题是一个“为什么?”,所以当我注意到它是一个“如何?”时,我决定非常好地记录“为什么”部分。123的技巧非常不错! - fedorqui

2
因此,我接受了@123的答案,这是我选择的答案:
mkdir -p "$DEST_ROOT_PATH/"{"$DEST_DIR1","$DEST_DIR2"}
mkdir -p "$DEST_ROOT_PATH/"{"$DEST_DIR3","$DEST_DIR4"}

这里没有很多目标目录,所以我认为这是花哨而令人讨厌的破解和会破坏缩进的反斜杠之间的良好平衡。

1
你可以考虑使用数组来存储这些值,然后通过循环遍历它们。 - fedorqui
确实。谢谢你的帮助。 - Amessihel

1
我会按照以下方式进行操作(虽然它只涉及您创建多个目录的特定任务,但并未回答标题中提出的问题):
for d in \
      "$DEST_DIR1" \
      "$DEST_DIR2" \
       ...         \
      "$DEST_DIRn" \
      ;
do
    mkdir -p "$DEST_ROOT_PATH/$d"
done

这种方法的优点在于维护列表会更容易一些。
通常情况下,当你注意到语法糖开始导致不便时,应该停止使用。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接