Линии продолжения Bash - PullRequest
       19

Линии продолжения Bash

132 голосов
/ 06 сентября 2011

Как вы используете строки продолжения bash?

Я понимаю, что вы можете сделать это:

echo "continuation \
lines"
>continuation lines

Однако, если у вас есть код с отступом, он работает не так хорошо:

    echo "continuation \
    lines"
>continuation     lines

Ответы [ 9 ]

141 голосов
/ 06 сентября 2011

Это то, что вам может понадобиться

$       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

Это позволит вам получить чистый код с отступом за счет дополнительных переменных.Если вы сделаете переменные локальными, это не должно быть слишком плохо.

25 голосов
/ 06 сентября 2011

Здесь документы с терминатором <<-HERE хорошо работают для многострочных текстовых строк с отступом.Это удалит все ведущие вкладки из документа здесь.(Тем не менее, терминаторы строки останутся.)

cat <<-____HERE
    continuation
    lines
____HERE

См. Также http://ss64.com/bash/syntax-here.html

Если вам нужно сохранить некоторые, но не все, первые пробелы, вы можете использовать что-то вроде

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

Для наложения длинных сложных строк на несколько строк мне нравится printf:

printf '%s' \
    "This will all be printed on a " \
    "single line (because the format string " \
    "doesn't specify any newline)"
7 голосов
/ 18 октября 2017

Вы можете использовать массивы bash

$ str_array=("continuation"
             "lines")

тогда

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

есть дополнительный пробел, потому что (после руководства bash):

Если слово заключено в двойные кавычки, ${name[*]} расширяется до одного слова с значение каждого члена массива, разделенного первым символом Переменная IFS

Итак, установите IFS='', чтобы избавиться от лишнего пространства

$ IFS=''
$ echo "${str_array[*]}"
continuationlines
2 голосов
/ 28 июля 2016

Я столкнулся с ситуацией, в которой мне приходилось отправлять длинное сообщение как часть аргумента команды и придерживаться ограничения длины строки. Команды выглядят примерно так:

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, каждая из которых отделена самим документом (из-за использования <<-) В конце все еще есть разрывы строк, которые затем заменяются на dd пробелами.

Обратите внимание, что если вы не удаляете символы новой строки, они будут отображаться как есть, когда "$message" развернуто. В некоторых случаях вы можете обойти эту проблему, удалив двойные кавычки вокруг $message, но сообщение больше не будет единственным аргументом.

1 голос
/ 27 июля 2018

Это не совсем то, что просил пользователь, но другой способ создать длинную строку, которая охватывает несколько строк, - это постепенно наращивать ее, например, так:

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

Очевидно, что в этом случае было бы проще создать его за один раз, но этот стиль может быть очень легким и понятным при работе с более длинными строками.

1 голос
/ 09 марта 2018

Вы можете просто отделить его с помощью новых строк (без использования обратной косой черты), как требуется внутри отступа, как показано ниже, и просто обрезать строки.

Пример:

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
0 голосов
/ 08 ноября 2018

В зависимости от того, какие риски вы принимаете и насколько хорошо вы знаете и доверяете данным, вы можете использовать упрощенную интерполяцию переменных.

$: 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
0 голосов
/ 29 июля 2016

Однако, если у вас есть код с отступом, он не очень хорошо работает:

    echo "continuation \
    lines"
>continuation     lines

Попробуйте использовать одинарные кавычки и объединить строки:

    echo 'continuation' \
    'lines'
>continuation lines

Примечание: конкатенация содержит пробелы.

0 голосов
/ 07 сентября 2011

Возможно, это на самом деле не отвечает на ваш вопрос, но вы все равно можете найти его полезным.

Первая команда создает сценарий, который отображается второй командой.

Третья команда делает этоисполняемый скрипт.

Четвертая команда предоставляет пример использования.

john@malkovich:~/tmp/so$ echo $'#!/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 работает.

Если используется $'...' или "$(...)" сбивает вас с толку, задайте другой вопрос (по одному на конструкцию), если его еще нет.Возможно, было бы неплохо предоставить ссылку на вопрос, который вы нашли / задали, чтобы другие люди имели связанную ссылку.

...