Как разделить строковый аргумент в bash на несколько строк без добавления пробела

Когда вы находитесь в командном режиме в vi (фактический редактор или режим Bash), нажатие цифр вводит аргумент (отсюда «arg»), который обычно используется для установки количества повторений. для выполнения следующей команды. Чтобы этого избежать, вы должны перейти в режим ввода (например, нажав i ) перед тем, как нажимать цифры.

Демонстрация:

Если вы не находитесь в режиме vi, вы можете войти в него, используя:

set -o vi

(Вы можете выйти из режима vi, войдя в режим emacs: set -o emacs )

Теперь, в режиме ввода vi введите такую ​​команду:

echo abcdefghijk4

Вы заметите, что в конце вы получите цифру «4», как показано выше.

Теперь нажмите Esc . Курсор переместится на один символ влево, и вы перейдете в командный режим.

Нажмите цифру, скажем «3». Теперь вы увидите это:

(arg: 3) echo abcdefghijk4

Теперь нажмите заглавную X. Вы должны увидеть:

echo abcdefgh4

Три символа («ijk») были удалены, потому что вы указали Readline (редактор ввода командной строки Bash) «стирать» 3 символа .

Теперь нажмите i и любую цифру. Цифра была вставлена ​​в командную строку в том месте, где находился курсор.

0
09.03.2019, 11:28
2 ответа
some_command --flag "$(printf '%s' foo\
    bar\
    quux)" arg2

подойдет, хотя это не самый читаемый текст. Это передает «foo», «bar» и «quux» в качестве аргументов команде printfс %sв качестве строки формата. Когда символов формата задано меньше, чем аргументов, строка формата повторяется по мере необходимости, что делает ее эквивалентной %s%s%s, или все три строки печатаются одна за другой без пробелов между ними. Наконец, вывод команды printf, «foobarquux», подставляется в качестве аргумента для some_command.

2
28.01.2020, 02:30

Использование вспомогательной функции:

concat () (
    IFS=
    printf '%s' "$*"
)

printf '"%s"\n' "$(concat "foo" \
    "bar" \
    "baz" )"

Это выведет

"foobarbaz"

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

concat () (
    IFS=
    printf '%s' "$*"
)

args=(
    "foo"
    "bar"
    "baz"
)

concat_args=$( concat "${args[@]}" )

printf '"%s"\n' "$concat_args"

То же, что и выше, но с оболочкой POSIX.:

concat () (
    IFS=
    printf '%s' "$*"
)

set -- \
   "foo" \
   "bar" \
   "baz"

concat_args=$( concat "$@" )

printf '"%s"\n' "$concat_args"

Обратите внимание, что тело функции concatвыполняется в своей собственной подоболочке (, что и (...)делает ), что означает, что изменение в IFSявляется локальным для функции.

Обоснование использования "$*"вместо "$@"в функции чисто для эстетики. "$*"расширится до одиночной строки, которая printfбудет напечатана. Фактическая конкатенация в этом случае выполняется расширением оболочки $*без разделителя (пустым$IFS). Вместо этого использование "$@"расширило бы количество отдельных строк, к которым printfнеоднократно применяла бы свою строку формата. Конкатенация в этом случае будет побочным эффектом использования конкретной строки формата с printf.

Или та же идея (создание фактической строки аргумента отдельно ), но без этой вспомогательной функции,

arg=\
"foo"\
"bar"\
"baz"

printf '"%s"\n' "$arg"

printf '"%s"\n'выше во всех случаях будет заменен вашим some_command --flag.

1
28.01.2020, 02:30

Теги

Похожие вопросы