Я пытаюсь сохранить несколько строк в переменной bash, но, похоже, это не работает.
Например, если я перечисляю по /bin
одному файлу в строке и сохраняю его $LS
, я передаю $LS
как stdin wc
, он всегда возвращает 1:
$ ls -1 /bin | wc -l
134
$ LS=$(ls -1 /bin); wc -l <<< $LS
1
Если я пытаюсь вывести на экран, я получаю различные результаты: echo
печатает все строки в одной строке, а printf
печатает только первую строку:
#!/bin/bash
LS=$(ls -1 /bin)
echo $LS
printf $LS
Итак, переменная bash может содержать несколько строк?
printf "%s\n" $LS
они это сделают.wc
другими командами:wc -l <<< "$LS"
printf '%s\n' "$LS"
если хотите видеть новую строку. Это неправильный набор, исправил это!Новые строки находятся в переменной.
LS=$(ls -1)
устанавливает переменнуюLS
на выходls -1
(который производит тот же вывод, что иls
, кстати, за исключением случаев, когда выход идет на терминал), минуя завершающие символы новой строки.Проблема в том, что вы удаляете символы новой строки при распечатывании значения. В сценарии оболочки
$LS
это не означает «значение переменнойLS
», это означает «принять значениеLS
, разбить его на слова в соответствииIFS
и интерпретировать каждое слово как шаблон глобуса». Чтобы получить значениеLS
, вам нужно написать"$LS"
или, в более общем случае, поставить$LS
между двойными кавычками.echo "$LS"
печатает значениеLS
, за исключением некоторых оболочек, которые интерпретируют символы обратной косой черты, и за исключением нескольких значений, начинающихся с-
.printf "$LS"
печатает значение,LS
пока оно не содержит символов процента или обратной косой черты и (с большинством реализаций) не начинается с-
.Чтобы напечатать значение
LS
точно, используйтеprintf %s "$LS"
. Если вы хотите новую строку в конце, используйтеprintf '%s\n' "$LS"
.Обратите внимание, что
$(ls)
в общем случае это не список файлов в текущем каталоге. Это работает только тогда, когда у вас есть достаточно прирученные имена файлов. Чтобы получить список имен файлов (кроме точечных файлов), необходимо использовать подстановочные:*
. Результатом является список строк, а не строка, поэтому вы не можете присвоить ее строковой переменной; Вы можете использовать переменную массиваfiles=(*)
в оболочках, которые их поддерживают (ksh93, bash, zsh).Для получения дополнительной информации см. Почему мой сценарий оболочки задыхается от пробелов или других специальных символов?
источник
Вышеупомянутое
это единственно правильное решение.
Позвольте мне продемонстрировать, что другие предложенные решения, как с, так
echo
иprintf
просто не работают должным образом:(Можно также проверить с
V=$(printf 'line0:\\n\\n\nline1.\n') printf '%s\n' "$V"
и вариации.)В то время как
\n
в именах файлов может быть не так часто, сохранитьgit diff
в переменной, и ваши шансы встретить литерал\n
резко возрастет.источник
ksh
иzsh
поддержка,print -r -- "$LS"
аzsh
также имеетecho -E - $LS
.csh
имеет ,echo $LS:q
однако , что не выводит символ новой строки , если $ LS пуста, и получить многострочное значение в $ LS в первую очередь , это довольно сложно в CSH.