How to write fancy-indented multi-line brace expansion in Bash?

你说的曾经没有我的故事 提交于 2019-12-14 03:48:49

问题


I'm dealing with a line such :

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

This line is quite long. I want to cut it so its width will fit into a 80 columns line. I tried to escape an end of line with a backslash, but space alignement breaks the expansion :

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

回答1:


You could use this disgusting hack.

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

It opens a subshell with nothing in it, but gets processed before the expansion so the expansion just sees an empty space




回答2:


This is the normal behaviour. From the Bash reference manual:

3.5.1 Brace expansion

Brace expansion is a mechanism by which arbitrary strings may be generated. This mechanism is similar to filename expansion (see Filename Expansion), but the filenames generated need not exist. Patterns to be brace expanded take the form of an optional preamble, followed by either a series of comma-separated strings or a sequence expression between a pair of braces, followed by an optional postscript. The preamble is prefixed to each string contained within the braces, and the postscript is then appended to each resulting string, expanding left to right.

Brace expansion does not allow spaces in between elements that get placed between \ and the next element in the following line.

And why? Because it gets removed when being processed:

3.1.2.1 Escape Character

A non-quoted backslash ‘\’ is the Bash escape character. It preserves the literal value of the next character that follows, with the exception of newline. If a \newline pair appears, and the backslash itself is not quoted, the \newline is treated as a line continuation (that is, it is removed from the input stream and effectively ignored).

So when you say

something + \ + <new line> + another_thing

Bash converts it into

something + another_thing

What can you do, then?

Add a backslash and then start writing from the very beginning on the next line:

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

Some examples

When you say:

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

And then move the arrow up you'll see this is the command that was performed:

$ echo "ha"{a,b   c}

So just say:

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

And you'll see this when moving up:

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

Another example:

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



回答3:


Thus I accepted @123's answer, here's the one I choosed :

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

There are not a lot of destination directories here, so I think it's a good balance between the fancy-and-disgusting hack and the frustrating backslash which breaks the indentation.




回答4:


I would do it is follows (though it only addresses your particular task of creating multiple directories and doesn't answer the question as stated in the title):

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

The advantage of this approach is that maintaining the list is a little easier.

In general, you should stop sticking to syntactic sugar when you notice that it starts causing inconveniences.



来源:https://stackoverflow.com/questions/37814739/how-to-write-fancy-indented-multi-line-brace-expansion-in-bash

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!