Многострочная строка с дополнительным пространством (сохраненный отступ)
Я хочу записать некоторые предварительно определенные тексты в файл со следующим:
text="this is line one\n
this is line two\n
this is line three"
echo -e $text > filename
Я ожидаю что-то вроде этого:
this is line one
this is line two
this is line three
Но получилось:
this is line one
this is line two
this is line three
Я уверен, что после каждого \n
нет пробела, но как выходит дополнительное пространство?
Ответы
Ответ 1
Эредок звучит для этого удобнее. Он используется для отправки нескольких команд в программу интерпретатора команд, например ex или cat
cat << EndOfMessage
This is line 1.
This is line 2.
Line 3.
EndOfMessage
Строка после <<
указывает, где остановиться.
Чтобы отправить эти строки в файл, используйте:
cat > $FILE <<- EOM
Line 1.
Line 2.
EOM
Вы также можете сохранить эти строки в переменной:
read -r -d '' VAR << EOM
This is line 1.
This is line 2.
Line 3.
EOM
Это сохраняет строки в переменной с именем VAR
.
При печати запомните кавычки вокруг переменной, иначе вы не увидите символы новой строки.
echo "$VAR"
Более того, вы можете использовать отступы, чтобы они выделялись в вашем коде. На этот раз просто добавьте -
после <<
чтобы закладки не появлялись.
read -r -d '' VAR <<- EOM
This is line 1.
This is line 2.
Line 3.
EOM
Но тогда вы должны использовать табуляции, а не пробелы, для отступа в вашем коде.
Ответ 2
Если вы пытаетесь получить строку в переменной, другой простой способ выглядит примерно так:
USAGE=$(cat <<-END
This is line one.
This is line two.
This is line three.
END
)
Если вы введете строку с вкладками (т.е. '\ t'), отступ будет удален. Если вы отступаете с пробелами, отступ будет оставлен.
ПРИМЕЧАНИЕ. Важно отметить, что последняя закрывающая скобка находится на другой строке. Текст END
должен отображаться на отдельной строке.
Ответ 3
echo
добавляет пробелы между переданными ему аргументами. $text
подвержен переменному расширению и разбиению слов, поэтому ваша команда echo
эквивалентна:
echo -e "this" "is" "line" "one\n" "this" "is" "line" "two\n" ...
Вы можете увидеть, что пространство будет добавлено до "this". Вы можете удалить символы новой строки и указать $text
, чтобы сохранить символы новой строки:
text="this is line one
this is line two
this is line three"
echo "$text" > filename
Или вы можете использовать printf
, который является более надежным и портативным, чем echo
:
printf "%s\n" "this is line one" "this is line two" "this is line three" > filename
В bash
, который поддерживает расширение фигурной скобки, вы можете даже сделать:
printf "%s\n" "this is line "{one,two,three} > filename
Ответ 4
в bash script выполняются следующие работы:
#!/bin/sh
text="this is line one\nthis is line two\nthis is line three"
echo $text > filename
альтернативный вариант:
text="this is line one
this is line two
this is line three"
echo "$text" > filename
cat filename дает:
this is line one
this is line two
this is line three
Ответ 5
Я нашел больше решений, так как я хотел, чтобы каждая строка имела правильный отступ:
-
Вы можете использовать echo
:
echo "this is line one" \
"\n""this is line two" \
"\n""this is line three" \
> filename
Это не работает, если вы ставите "\n"
непосредственно перед \
в конце строки.
-
Кроме того, вы можете использовать printf
для лучшей переносимости (у меня было много проблем с echo
):
printf '%s\n' \
"this is line one" \
"this is line two" \
"this is line three" \
> filename
-
Еще одно решение может быть:
text=''
text="${text}this is line one\n"
text="${text}this is line two\n"
text="${text}this is line three\n"
printf "%b" "$text" > filename
или же
text=''
text+="this is line one\n"
text+="this is line two\n"
text+="this is line three\n"
printf "%b" "$text" > filename
-
Другое решение достигается путем смешивания printf
и sed
.
if something
then
printf '%s' '
this is line one
this is line two
this is line three
' | sed '1d;$d;s/^ //g'
fi
Реорганизовать код, отформатированный таким образом, нелегко, поскольку вы жестко закодировали уровень отступа в коде.
-
Можно использовать вспомогательную функцию и некоторые приемы подстановки переменных:
unset text
_() { text="${text}${text+
}${*}"; }
# That an empty line which demonstrates the reasoning behind
# the usage of "+" instead of ":+" in the variable substitution
# above.
_ ""
_ "this is line one"
_ "this is line two"
_ "this is line three"
unset -f _
printf '%s' "$text"
Ответ 6
Ниже приведен мой предпочтительный способ назначения многострочной строки переменной (я думаю, это выглядит хорошо).
read -r -d '' my_variable << \
_______________________________________________________________________________
String1
String2
String3
...
StringN
_______________________________________________________________________________
Количество подчеркиваний одинаково (здесь 80) в обоих случаях.
Ответ 7
это будет работать, если вы поставите его как показано ниже:
AA='first line
\nsecond line
\nthird line'
echo $AA
output:
first line
second line
third line
Ответ 8
Что если вы читаете многострочный вывод из скрипта?
Я пытался сделать что-то вроде...
OUTPUT экспорта = $ (ls -Fla/тонну)
... и когда я делаю...
echo $ OUTPUT
... это довольно некрасиво...
всего 36 drwxrwxrwt 9 корневой корень 4096 апр. 5 20:09./drwxr-xr-x 24 корневой корень 4096 апр. 3 06:46../drwxrwxrwt 2 корневой корень 4096 18 марта 18:26.ICE-unix/drwxrwxrwt 2 корневой корень 4096 18 марта 18:26.Test-unix/drwxrwxrwt 2 root root 4096 Mar 18 18:26.X11-unix/drwxrwxrwt 2 root root 4096 18 марта 18:26.XIM-unix/drwxrwxrwt 2 root root 4096 18 марта 18: 26.font-unix/drwx------ 3 корневой корень 4096 18 марта 18:26 systemd-private-21ccc8c939c9415fb522b60ed197c724-systemd-resolved.service-SnudvR/drwx------ 3 корневой корень 4096 18 марта 18:26 systemd-private-21ccc8c939c9415fb722606077 Systemd-timesyncd.service-C49grY/
Я пытаюсь запустить скрипт, сохранить отформатированный текст в переменную, а затем передать его в SMS в AWS, но преобразование в переменную, похоже, разрушает форматирование.
Есть идеи?