如何在 Bash 中将字符串拆分为多行?

发布于 2024-12-03 03:32:32 字数 232 浏览 1 评论 0原文

如何将长字符串常量拆分为多行?

我意识到你可以这样做:

echo "continuation \
lines"
>continuation lines

但是,如果你有缩进代码,效果就不太好:

    echo "continuation \
    lines"
>continuation     lines

How can i split my long string constant over multiple lines?

I realize that you can do this:

echo "continuation \
lines"
>continuation lines

However, if you have indented code, it doesn't work out so well:

    echo "continuation \
    lines"
>continuation     lines

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(12

时光沙漏 2024-12-10 03:32:32

这就是您可能想要的

$       echo "continuation"\
>       "lines"
continuation lines

如果这会创建两个 echo 参数,而您只需要一个,那么让我们看看字符串连接。在 bash 中,将两个字符串并排放置在一起:

$ echo "continuation""lines"
continuationlines

因此,不带缩进的续行是分解字符串的一种方法:

$ echo "continuation"\
> "lines"
continuationlines

但是当使用缩进时:

$       echo "continuation"\
>       "lines"
continuation lines

您会得到两个参数,因为这不是更长的串联。

如果您想要一个跨行的字符串,同时缩进但没有获得所有这些空格,您可以尝试的一种方法是放弃续行并使用变量:

$ a="continuation"
$ b="lines"
$ echo $a$b
continuationlines

这将允许您以额外变量为代价获得干净的缩进代码。如果你将变量设置为本地变量,那应该不会太糟糕。

This is what you may want

$       echo "continuation"\
>       "lines"
continuation lines

If this creates two arguments to echo and you only want one, then let's look at string concatenation. In bash, placing two strings next to each other concatenate:

$ echo "continuation""lines"
continuationlines

So a continuation line without an indent is one way to break up a string:

$ echo "continuation"\
> "lines"
continuationlines

But when an indent is used:

$       echo "continuation"\
>       "lines"
continuation lines

You get two arguments because this is no longer a concatenation.

If you would like a single string which crosses lines, while indenting but not getting all those spaces, one approach you can try is to ditch the continuation line and use variables:

$ a="continuation"
$ b="lines"
$ echo $a$b
continuationlines

This will allow you to have cleanly indented code at the expense of additional variables. If you make the variables local it should not be too bad.

ペ泪落弦音 2024-12-10 03:32:32

这里带有 <<-HERE 终止符的文档非常适合缩进的多行文本字符串。它将从此处文档中删除所有前导选项卡。 (不过,行终止符仍将保留。)

cat <<-____HERE
    continuation
    lines
____HERE

(Stack Overflow 将制表符呈现为空格,因此您无法直接从此处复制/粘贴代码。我在 continuationlines< 之前确实使用了文字制表符/code> 在此答案的来源中。)

另请参阅 http://ss64.com/bash/syntax-here.html

如果您需要保留一些(但不是全部)前导空格,您可以使用类似的内容

sed 's/^  //' <<____HERE
    This has four leading spaces.
    Two of them will be removed by sed.
____HERE

或可能使用 tr 摆脱换行符:(

tr -d '\012' <<-____
    continuation
     lines
____

第二行前面有一个制表符和一个空格;制表符将由破折号运算符在定界符终止符之前删除,而空格将被保留。)

用于将长的复杂字符串包装在许多线条,我喜欢printf

printf '%s' \
    "This will all be printed on a " \
    "single line (because the format string " \
    "doesn't specify any newline)"

如果您想要将重要的 shell 脚本片段嵌入另一种语言,而宿主语言的语法不允许您使用此处文档,例如在 中,它也能很好地工作。 MakefileDockerfile

printf '%s\n' >./myscript \
    '#!/bin/sh` \
    "echo \"G'day, World\"" \
    'date +%F\ %T' && \
chmod a+x ./myscript && \
./myscript

对于重要的需求,也许还探索%b printf 的格式字符串说明符。 (不过,这只是 Bash。)

Here documents with the <<-HERE terminator work well for indented multi-line text strings. It will remove any leading tabs from the here document. (Line terminators will still remain, though.)

cat <<-____HERE
    continuation
    lines
____HERE

(Stack Overflow renders tabs as spaces, so you cannot copy/paste the code directly from here. I did use literal tabs before continuation and lines in the source of this answer.)

See also http://ss64.com/bash/syntax-here.html

If you need to preserve some, but not all, leading whitespace, you might use something like

sed 's/^  //' <<____HERE
    This has four leading spaces.
    Two of them will be removed by sed.
____HERE

or maybe use tr to get rid of newlines:

tr -d '\012' <<-____
    continuation
     lines
____

(The second line has a tab and a space up front; the tab will be removed by the dash operator before the heredoc terminator, whereas the space will be preserved.)

For wrapping long complex strings over many lines, I like printf:

printf '%s' \
    "This will all be printed on a " \
    "single line (because the format string " \
    "doesn't specify any newline)"

It also works well in contexts where you want to embed nontrivial pieces of shell script in another language where the host language's syntax won't let you use a here document, such as in a Makefile or Dockerfile.

printf '%s\n' >./myscript \
    '#!/bin/sh` \
    "echo \"G'day, World\"" \
    'date +%F\ %T' && \
chmod a+x ./myscript && \
./myscript

For nontrivial needs, perhaps also explore the %b format string specifier for printf. (This is Bash only, though.)

少跟Wǒ拽 2024-12-10 03:32:32

您可以使用 bash 数组

$ str_array=("continuation"
             "lines")

然后

$ echo "${str_array[*]}"
continuation lines

有一个额外的空格,因为(bash手册之后):

如果单词被双引号括起来,${name[*]} 会扩展为单个单词
每个数组成员的值由第一个字符分隔
IFS变量

因此设置 IFS='' 来消除多余的空间

$ IFS=''
$ echo "${str_array[*]}"
continuationlines

You can use bash arrays

$ str_array=("continuation"
             "lines")

then

$ echo "${str_array[*]}"
continuation lines

there is an extra space, because (after bash manual):

If the word is double-quoted, ${name[*]} expands to a single word with
the value of each array member separated by the first character of the
IFS variable

So set IFS='' to get rid of extra space

$ IFS=''
$ echo "${str_array[*]}"
continuationlines
原野 2024-12-10 03:32:32

在某些情况下,利用 Bash 的串联能力可能是合适的。

示例:

temp='this string is very long '
temp+='so I will separate it onto multiple lines'
echo $temp
this string is very long so I will separate it onto multiple lines

从 Bash 手册页的 PARAMETERS 部分:

名称=[值]...

...在赋值语句将值赋给 shell 变量或数组索引的上下文中,+= 运算符可用于追加或添加到变量的先前值。当 += 应用于已设置整数属性的变量时, value 将作为算术表达式进行计算,并添加到变量的当前值上,该值也会被计算。当使用复合赋值将 += 应用于数组变量时(请参阅下面的数组),该变量的值不会取消设置(与使用 = 时一样),并且新值会从比数组最大索引大 1 的位置开始附加到数组中(对于索引数组)或作为附加键值对添加到关联数组中。 当应用于字符串值变量时,值会扩展并附加到变量的值中。

In certain scenarios utilizing Bash's concatenation ability might be appropriate.

Example:

temp='this string is very long '
temp+='so I will separate it onto multiple lines'
echo $temp
this string is very long so I will separate it onto multiple lines

From the PARAMETERS section of the Bash Man page:

name=[value]...

...In the context where an assignment statement is assigning a value to a shell variable or array index, the += operator can be used to append to or add to the variable's previous value. When += is applied to a variable for which the integer attribute has been set, value is evaluated as an arithmetic expression and added to the variable's current value, which is also evaluated. When += is applied to an array variable using compound assignment (see Arrays below), the variable's value is not unset (as it is when using =), and new values are appended to the array beginning at one greater than the array's maximum index (for indexed arrays) or added as additional key-value pairs in an associative array. When applied to a string-valued variable, value is expanded and appended to the variable's value.

十二 2024-12-10 03:32:32

您可以根据缩进中的需要简单地用换行符(不使用反斜杠)将其分隔开,如下所示,然后删除新行。

示例:

echo "continuation
of 
lines" | tr '\n' ' '

或者,如果它是变量定义,则换行符会自动转换为空格。因此,仅在适用时删除额外的空格。

x="continuation
of multiple
lines"
y="red|blue|
green|yellow"

echo $x # This will do as the converted space actually is meaningful
echo $y | tr -d ' ' # Stripping of space may be preferable in this case

You could simply separate it with newlines (without using backslash) as required within the indentation as follows and just strip of new lines.

Example:

echo "continuation
of 
lines" | tr '\n' ' '

Or if it is a variable definition newlines gets automatically converted to spaces. So, strip of extra spaces only if applicable.

x="continuation
of multiple
lines"
y="red|blue|
green|yellow"

echo $x # This will do as the converted space actually is meaningful
echo $y | tr -d ' ' # Stripping of space may be preferable in this case
紫南 2024-12-10 03:32:32

这并不完全是用户所要求的,但创建跨多行的长字符串的另一种方法是逐步构建它,如下所示:

$ greeting="Hello"
$ greeting="$greeting, World"
$ echo $greeting
Hello, World

显然,在这种情况下,一次构建它会更简单,但这种风格在处理较长的字符串时可以非常轻量级且易于理解。

This isn't exactly what the user asked, but another way to create a long string that spans multiple lines is by incrementally building it up, like so:

$ greeting="Hello"
$ greeting="$greeting, World"
$ echo $greeting
Hello, World

Obviously in this case it would have been simpler to build it one go, but this style can be very lightweight and understandable when dealing with longer strings.

┼── 2024-12-10 03:32:32

行延续也可以通过巧妙地使用语法来实现。

对于 echo 的情况:

# echo '-n' flag prevents trailing <CR> 
echo -n "This is my one-line statement" ;
echo -n " that I would like to make."
This is my one-line statement that I would like to make.

对于 vars 的情况:

outp="This is my one-line statement" ; 
outp+=" that I would like to make." ; 
echo -n "${outp}"
This is my one-line statement that I would like to make.

对于 vars 的另一种方法:

outp="This is my one-line statement" ; 
outp="${outp} that I would like to make." ; 
echo -n "${outp}"
This is my one-line statement that I would like to make.

瞧!

Line continuations also can be achieved through clever use of syntax.

In the case of echo:

# echo '-n' flag prevents trailing <CR> 
echo -n "This is my one-line statement" ;
echo -n " that I would like to make."
This is my one-line statement that I would like to make.

In the case of vars:

outp="This is my one-line statement" ; 
outp+=" that I would like to make." ; 
echo -n "${outp}"
This is my one-line statement that I would like to make.

Another approach in the case of vars:

outp="This is my one-line statement" ; 
outp="${outp} that I would like to make." ; 
echo -n "${outp}"
This is my one-line statement that I would like to make.

Voila!

阳光下的泡沫是彩色的 2024-12-10 03:32:32

我遇到过一种情况,我必须发送一条长消息作为命令参数的一部分,并且必须遵守行长度限制。命令看起来像这样:

somecommand --message="I am a long message" args

我解决这个问题的方法是将消息作为此处文档移出(就像 @tripleee 建议的那样)。但是这里的文档变成了标准输入,所以需要读回它,我采用了以下方法:

message=$(
    tr "\n" " " <<-END
        This is a
        long message
END
)
somecommand --message="$message" args

这样做的优点是 $message 可以完全用作字符串常量,没有额外的空格或换行符。

请注意,上面的实际消息行均以 tab 字符为前缀,该字符被此处文档本身删除(因为使用 <<-)。末尾仍然有换行符,然后用带有空格的 tr 替换。

另请注意,如果您不删除换行符,它们将在 "$message" 展开时按原样显示。在某些情况下,您可以通过删除 $message 周围的双引号来解决此问题,但该消息将不再是单个参数。

I came across a situation in which I had to send a long message as part of a command argument and had to adhere to the line length limitation. The commands looks something like this:

somecommand --message="I am a long message" args

The way I solved this is to move the message out as a here document (like @tripleee suggested). But a here document becomes a stdin, so it needs to be read back in, I went with the below approach:

message=$(
    tr "\n" " " <<-END
        This is a
        long message
END
)
somecommand --message="$message" args

This has the advantage that $message can be used exactly as the string constant with no extra whitespace or line breaks.

Note that the actual message lines above are prefixed with a tab character each, which is stripped by here document itself (because of the use of <<-). There are still line breaks at the end, which are then replaced by tr with spaces.

Note also that if you don't remove newlines, they will appear as is when "$message" is expanded. In some cases, you may be able to workaround by removing the double-quotes around $message, but the message will no longer be a single argument.

少女的英雄梦 2024-12-10 03:32:32

根据您将接受的风险类型以及您对数据的了解和信任程度,您可以使用简单的变量插值。

$: x="
    this
    is
       variably indented
    stuff
   "
$: echo "$x" # preserves the newlines and spacing

    this
    is
       variably indented
    stuff

$: echo $x # no quotes, stacks it "neatly" with minimal spacing
this is variably indented stuff

Depending on what sort of risks you will accept and how well you know and trust the data, you can use simplistic variable interpolation.

$: x="
    this
    is
       variably indented
    stuff
   "
$: echo "$x" # preserves the newlines and spacing

    this
    is
       variably indented
    stuff

$: echo $x # no quotes, stacks it "neatly" with minimal spacing
this is variably indented stuff
再可℃爱ぅ一点好了 2024-12-10 03:32:32

按照 @tripleee 的 printf 示例 (+1):

LONG_STRING=$( printf '%s' \
    'This is the string that never ends.' \
    ' Yes, it goes on and on, my friends.' \
    ' My brother started typing it not knowing what it was;' \
    " and he'll continue typing it forever just because..." \
    ' (REPEAT)' )

echo $LONG_STRING

This is the string that never ends. Yes, it goes on and on, my friends. My brother started typing it not knowing what it was; and he'll continue typing it forever just because... (REPEAT)

我们在句子之间添加了明确的空格,例如“' Yes​​...”。另外,如果我们可以不使用变量:

echo "$( printf '%s' \
    'This is the string that never ends.' \
    ' Yes, it goes on and on, my friends.' \
    ' My brother started typing it not knowing what it was;' \
    " and he'll continue typing it forever just because..." \
    ' (REPEAT)' )"

This is the string that never ends. Yes, it goes on and on, my friends. My brother started typing it not knowing what it was; and he'll continue typing it forever just because... (REPEAT)

对永无止境的歌曲的致谢

Following @tripleee 's printf example (+1):

LONG_STRING=$( printf '%s' \
    'This is the string that never ends.' \
    ' Yes, it goes on and on, my friends.' \
    ' My brother started typing it not knowing what it was;' \
    " and he'll continue typing it forever just because..." \
    ' (REPEAT)' )

echo $LONG_STRING

This is the string that never ends. Yes, it goes on and on, my friends. My brother started typing it not knowing what it was; and he'll continue typing it forever just because... (REPEAT)

And we have included explicit spaces between the sentences, e.g. "' Yes...". Also, if we can do without the variable:

echo "$( printf '%s' \
    'This is the string that never ends.' \
    ' Yes, it goes on and on, my friends.' \
    ' My brother started typing it not knowing what it was;' \
    " and he'll continue typing it forever just because..." \
    ' (REPEAT)' )"

This is the string that never ends. Yes, it goes on and on, my friends. My brother started typing it not knowing what it was; and he'll continue typing it forever just because... (REPEAT)

Acknowledgement for the song that never ends

秋千易 2024-12-10 03:32:32

但是,如果您有缩进代码,效果就不太好:

 echo "继续 \
    线”
>连续线

尝试使用单引号并连接字符串:

    echo 'continuation' \
    'lines'
>continuation lines

注意:连接包含空格。

However, if you have indented code, it doesn't work out so well:

    echo "continuation \
    lines"
>continuation     lines

Try with single quotes and concatenating the strings:

    echo 'continuation' \
    'lines'
>continuation lines

Note: the concatenation includes a whitespace.

ぶ宁プ宁ぶ 2024-12-10 03:32:32

这可能并不能真正回答您的问题,但您可能会发现它很有用。

第一个命令创建由第二个命令显示的脚本。

第三个命令使该脚本可执行。

第四个命令提供了使用示例。

john@malkovich:~/tmp/so$ echo 

请注意,如果您确实想使用此脚本,则将可执行脚本移至 ~/bin 中更有意义,这样它将位于您的路径中。

检查 python 参考以获取有关如何 textwrap.dedent< 的详细信息/a> 有效。

如果 $'...'"$(...)" 的用法令您感到困惑,请询问另一个问题(每个构造一个)(如果还没有)一起来。最好提供您找到/提出的问题的链接,以便其他人可以获得链接的参考。

#!/usr/bin/env python\nimport textwrap, sys\n\ndef bash_dedent(text):\n """Dedent all but the first line in the passed `text`."""\n try:\n first, rest = text.split("\\n", 1)\n return "\\n".join([first, textwrap.dedent(rest)])\n except ValueError:\n return text # single-line string\n\nprint bash_dedent(sys.argv[1])' > bash_dedent john@malkovich:~/tmp/so$ cat bash_dedent #!/usr/bin/env python import textwrap, sys def bash_dedent(text): """Dedent all but the first line in the passed `text`.""" try: first, rest = text.split("\n", 1) return "\n".join([first, textwrap.dedent(rest)]) except ValueError: return text # single-line string print bash_dedent(sys.argv[1]) john@malkovich:~/tmp/so$ chmod a+x bash_dedent john@malkovich:~/tmp/so$ echo "$(./bash_dedent "first line > second line > third line")" first line second line third line

请注意,如果您确实想使用此脚本,则将可执行脚本移至 ~/bin 中更有意义,这样它将位于您的路径中。

检查 python 参考以获取有关如何 textwrap.dedent< 的详细信息/a> 有效。

如果 $'...'"$(...)" 的用法令您感到困惑,请询问另一个问题(每个构造一个)(如果还没有)一起来。最好提供您找到/提出的问题的链接,以便其他人可以获得链接的参考。

This probably doesn't really answer your question but you might find it useful anyway.

The first command creates the script that's displayed by the second command.

The third command makes that script executable.

The fourth command provides a usage example.

john@malkovich:~/tmp/so$ echo 

Note that if you really want to use this script, it makes more sense to move the executable script into ~/bin so that it will be in your path.

Check the python reference for details on how textwrap.dedent works.

If the usage of $'...' or "$(...)" is confusing to you, ask another question (one per construct) if there's not already one up. It might be nice to provide a link to the question you find/ask so that other people will have a linked reference.

#!/usr/bin/env python\nimport textwrap, sys\n\ndef bash_dedent(text):\n """Dedent all but the first line in the passed `text`."""\n try:\n first, rest = text.split("\\n", 1)\n return "\\n".join([first, textwrap.dedent(rest)])\n except ValueError:\n return text # single-line string\n\nprint bash_dedent(sys.argv[1])' > bash_dedent john@malkovich:~/tmp/so$ cat bash_dedent #!/usr/bin/env python import textwrap, sys def bash_dedent(text): """Dedent all but the first line in the passed `text`.""" try: first, rest = text.split("\n", 1) return "\n".join([first, textwrap.dedent(rest)]) except ValueError: return text # single-line string print bash_dedent(sys.argv[1]) john@malkovich:~/tmp/so$ chmod a+x bash_dedent john@malkovich:~/tmp/so$ echo "$(./bash_dedent "first line > second line > third line")" first line second line third line

Note that if you really want to use this script, it makes more sense to move the executable script into ~/bin so that it will be in your path.

Check the python reference for details on how textwrap.dedent works.

If the usage of $'...' or "$(...)" is confusing to you, ask another question (one per construct) if there's not already one up. It might be nice to provide a link to the question you find/ask so that other people will have a linked reference.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文