Автоматическое преобразование новых строк в присвоении переменной оболочки

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

 > num=$(echo 6^6^3 | bc) > echo $num 12041208676482351082020900568572834033367326934574532243581212211450\ 20555710636789704085475234591191603986789604949502079328192358826561\ 895781636115334656050057189523456 

Но обратите внимание, что они не являются переломами строки в переменной – или, по крайней мере, нет, если они используются без кавычек. Например, при запуске с большим количеством каналов в присваивании, например:

 num=$(echo 6^6^3 | bc | perl -pne 's/\\\n//g') 

Я понял, что, хотя в выводе bc действительно есть \n , проверка echo $num > tmp.txt с echo $num > tmp.txt показывает, что \n (ASCII 10) определенно становится пространством (ASCII 32) в присваивании переменной.

Или, по крайней мере, на выходе без кавычек $num > . Почему это?

Как указывает Фёдоркви, если вы используете кавычки: echo "$num" , вы снова получите символы новой строки. Это видно из рассмотрения разницы между echo $num > tmp.1 и echo "$num" > tmp.2 с echo "$num" > tmp.2 ; первый содержит \ (обратная косая черта), тогда как более поздняя содержит \\n (обратная косая черта).

5 Solutions collect form web for “Автоматическое преобразование новых строк в присвоении переменной оболочки”

echo помещает пробел между двумя аргументами. Оболочка считает новую строку в $num просто разделителем слов (просто как пространство).

 lines="a b c" set -x echo $lines # several arguments to echo echo "$lines" # one argument to echo 

См. Этот ответ (сам OP) для более подробного объяснения.

Не знаю, почему его там, но вот как отключить его с реализацией GNU bc :

 echo '6^6^3' | BC_LINE_LENGTH=0 bc 

BC_LINE_LENGTH

Это должно быть целое число, указывающее количество символов в строке вывода для чисел. Это включает символы обратной косой черты и символы новой строки для длинных чисел. В качестве расширения значение нуля отключает многострочную функцию. Любое другое значение этой переменной, которая меньше 3, устанавливает длину линии до 70.

Обновить:

Я был смущен этим вопросом, я думал, что речь идет о происхождении многострочной функции, это кажется странным. Во всяком случае, реальный ответ заключается в том, что если вы не процитируете переменную, оболочка произведет на ней слово, пока это не будет передано в echo . Разделение слов – это процесс, когда разложение делится на «слова» в зависимости от содержимого IFS , эти «слова» затем становятся разными аргументами. В примере вопроса это создает два аргумента для эха, которые затем отделяются от пробела (я знал это до того, как Стефан прокомментировал, честный …).

Чтобы этого не произошло, просто дважды укажите переменную:

 num=$(echo '6^6^3' | bc) echo "$num" 

Иногда это действительно полезно как способ удаления символов IFS из переменной (хотя printf %s более безопасен для произвольных строк). Например (в bash ):

 $ var=$'spaces: newlines:\n\n\ntabs:\t\t\t end' $ echo "$var" spaces: newlines: tabs: end $ newvar="$(printf '%s ' $var)" $ echo "$newvar" spaces: newlines: tabs: end 

Используйте tr для удаления продолжений строки и строк новой строки:

 $ num=$(echo 6^6^3 | bc) $ echo "$num" 12041208676482351082020900568572834033367326934574532243581212211450\ 20555710636789704085475234591191603986789604949502079328192358826561\ 895781636115334656050057189523456 $ num=$(echo "$num" | tr -d '\n\\') $ echo "$num" 12041208676482351082020900568572834033367326934574532243581212211450205557106367897040854752345911916039867896049495020793281923588265618957816361153346560500571895 23456 

На странице bc man, в выражениях, это объясняет предел.

Поскольку числа имеют произвольную точность, некоторые номера могут не печататься на одной выходной строке. Эти длинные числа будут разбиты на строки, используя символ «\» в качестве последнего символа в строке. Максимальное количество символов, напечатанных на строку, равно 70.

Согласно замечанию Стефана Хазеласа , проблема не в том, что пространство интерпретируется как новая строка. Он объяснил это в другом месте относительно (концептуального) оператора «split + glob», и хотя я не полностью следую семантике этого, вот что происходит:

  • Некатегорованная переменная разделяется на пробелы оболочкой, и они передаются как аргументы для echo . Разделение удаляет пробелы. Это может быть немного запутанным, так как «обратная косая черта-новая линия» выглядит как escape-последовательность, но она НЕ эквивалентна x=\\\n , она эквивалентна x=$'\\\012' , \012 являющейся восьмеричной для фактическая строка новой строки – в отличие от escape-последовательности \\n , что приводит к тому, что строка содержит литерал «\ n» (обратная косая черта-n), который не будет разделен.

  • Затем echo выводит свои аргументы, разделенные пробелом.

Повторить:

 str1=hello\\nworld str2=$'hello\012world' 

Оболочка не будет разделять первую, не сортированную, так как на самом деле она не содержит пробелов – она ​​содержит escape-последовательность \n , тогда как во втором случае она будет разбита на кавычки символа фактической новой строки (это пробел).

  • Как отключить переменную в командной строке?
  • Прочитайте вывод команды в переменной
  • Bash - Как перебирать подкаталоги и извлекать файлы
  • Как изменить рабочий каталог вызова оболочки с помощью скрипта?
  • Как найти процессор и использование памяти для дочерних процессов
  • Разбор строки по awk и получить только элементы без труб или полуколонок
  • Соответствие шаблону ls
  • Как распечатать символ ASCII с помощью разных кодовых точек в Bash?
  • Сохранять коды выхода при захвате SIGINT и тому подобное?
  • Как искать слово во всем содержимом каталога в linux
  • Что такое $ () в команде?
  • Может ли сценарий bash сбросить и дезинфицировать * всю * среду и как?
  • Linux и Unix - лучшая ОС в мире.