Замените строку, содержащую шаблон в переменной Shell, но сохраняйте линейные каналы [duplicate]

В Java все находится в форме класса.

Если вы хотите использовать любой объект, тогда у вас есть две фазы:

  1. Объявить
  2. Инициализация

Пример:

  • Объявление: Object a;
  • Инициализация: a=new Object();

То же самое для концепции массива

  • Объявление: Item i[]=new Item[5];
  • Инициализация: i[0]=new Item();

Если вы не дают секцию инициализации, тогда возникает NullpointerException.

59
задан that other guy 31 March 2015 в 21:05
поделиться

6 ответов

Во всех вышеперечисленных случаях переменная правильно установлена, но неправильно прочитана! Правильный способ заключается в использовании двойных кавычек при ссылке на :

echo "$var"

Это дает ожидаемое значение во всех приведенных примерах. Всегда указывайте ссылки на переменные!


Почему?

Если переменная некорректна, она будет:

  1. Превращаться разделение поля , где значение разбивается на несколько слов по пробелам (по умолчанию) : До: /* Foobar is free software */ После: /*, Foobar, is, free, software, */
  2. Каждое из этих слов будет претерпевать расширение pathname , где шаблоны расширяются в файлы сопоставления: Before: /* После: /bin, /boot, /dev, /etc, /home, ...
  3. Наконец все аргументы передаются в echo, который записывает их , разделенные одиночными пробелами , давая
    /bin /boot /dev /etc /home Foobar is free software Desktop/ Downloads/
    
    вместо значения переменной.

Когда переменная цитируется:

  1. Подставлять его значение.
  2. Нет шага 2.

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

63
ответ дан that other guy 19 August 2018 в 08:00
поделиться

Дополнительно для размещения переменной в кавычках можно также перевести вывод переменной с помощью tr и преобразовать пробелы в строки новой строки.

$ echo $var | tr " " "\n"
foo
bar
baz

Хотя это немного запутанно, добавьте больше разнообразия с выходом, поскольку вы можете заменить любой символ как разделитель между переменными массива.

-2
ответ дан Alek 19 August 2018 в 08:00
поделиться
  • 1
    Но это заменяет пробелы all на новые строки. Котировка сохраняет существующие новые строки и пробелы. – user000001 20 May 2015 в 18:06
  • 2
    Правда, да. Я полагаю, это зависит от того, что находится внутри переменной. Фактически я использую tr для создания массивов из текстовых файлов. – Alek 20 May 2015 в 19:00
  • 3
    Создание проблемы, не ссылаясь на переменную должным образом, а затем работая с ней с помощью дополнительного процесса, созданного с помощью hamfisted, не является хорошим программированием. – tripleee 1 February 2016 в 07:22
  • 4
    @Alek, ... err, что? Нет никакого tr, необходимого для правильного / правильного создания массива из текстового файла - вы можете указать любой разделитель, который вы хотите, установив IFS. Например: IFS=$'\n' read -r -d '' -a arrayname < <(cat file.txt && printf '\0') работает полностью через bash 3.2 (самая старая версия в широком обращении) и правильно устанавливает статус выхода в false, если ваш cat не удалось. И если вы хотите, скажем, tabs вместо строк новой строки, вы просто замените $'\n' на $'\t'. – Charles Duffy 23 January 2017 в 22:43
  • 5
    @Alek, ... если вы делаете что-то вроде arrayname=( $( cat file | tr '\n' ' ' ) ), то это разбито на несколько слоев: он подталкивает ваши результаты (поэтому * превращается в список файлов в текущем каталоге) и он будет работать так же хорошо, как и tr (или cat, если на то пошло, можно просто использовать arrayname=$( $(<file) ), и он будет разбит одинаково, но менее неэффективно). – Charles Duffy 23 January 2017 в 22:45

Возможно, вам захочется узнать, почему это происходит. Вместе с великое объяснение этого другого парня найдет ссылку на . Почему мой сценарий оболочки задыхается от пробелов или других специальных символов? , написанный Жилем в Unix & amp; Linux :

Зачем мне писать "$foo"? Что происходит без кавычек?

$foo не означает «принять значение переменной foo». Это означает нечто гораздо более сложное:

  • Сначала возьмите значение переменной.
  • Разбиение поля: обрабатывайте это значение как список полей, разделенных пробелами, и создавайте результирующий список. Например, если переменная содержит foo * bar ​, то результатом этого шага будет 3-элементный список foo, *, bar.
  • Генерация имени файла: обрабатывайте каждое поле как глобус, т. е. как шаблон подстановочного знака, и заменяйте его на список имен файлов, соответствующих этому шаблону. Если шаблон не соответствует никаким файлам, он остается неизмененным. В нашем примере это приводит к списку, содержащему foo, следуя списку файлов в текущем каталоге и, наконец, bar. Если текущий каталог пуст, результат будет foo, *, bar.

Обратите внимание, что результатом является список строк. В контексте синтаксиса оболочки есть два контекста: контекст списка и контекст строки. Разделение поля и генерация имени файла происходят только в контексте списка, но это в большинстве случаев. Двойные кавычки ограничивают контекст строки: вся строка с двумя кавычками - это одна строка, которую нельзя разделить. (Исключение: "$@", чтобы перейти к списку позиционных параметров, например "$@" эквивалентно "$1" "$2" "$3", если есть три позиционных параметра. См. В чем разница между $ * и $ @? )

То же самое происходит с подстановкой команды с помощью $(foo) или с помощью `foo`. На стороне примечания не используйте `foo`: его правила цитирования являются странными и не переносимыми, и все современные оболочки поддерживают $(foo), что абсолютно эквивалентно, за исключением наличия интуитивных правил цитирования.

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

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

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

9
ответ дан Community 19 August 2018 в 08:00
поделиться
Выход

echo $var сильно зависит от значения переменной IFS. По умолчанию он содержит символы пробела, табуляции и новой строки:

[ks@localhost ~]$ echo -n "$IFS" | cat -vte
 ^I$

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

. Один из способов предотвратить разделение слов (помимо использования двойных кавычек) - установить IFS к null. См. http://pubs.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html#tag_02_06_05 :

Если значение IFS равно null, ни одно поле

Установка в значение null означает установку пустого значения:

IFS=

Тест:

[ks@localhost ~]$ echo -n "$IFS" | cat -vte
 ^I$
[ks@localhost ~]$ var=$'key\nvalue'
[ks@localhost ~]$ echo $var
key value
[ks@localhost ~]$ IFS=
[ks@localhost ~]$ echo $var
key
value
[ks@localhost ~]$ 
1
ответ дан ks1322 19 August 2018 в 08:00
поделиться
  • 1
    Вам также необходимо будет set -f, чтобы предотвратить зависание – that other guy 15 November 2015 в 19:31
  • 2
    @thatotherguy, действительно ли это необходимо для вашего 1-го примера с расширением пути? Если значение IFS установлено равным null, echo $var будет расширено до echo '/* Foobar is free software */', а расширение пути не будет выполняться внутри строк с одиночными кавычками. – ks1322 16 November 2015 в 10:02
  • 3
    Да. Если вы mkdir "/this thing called Foobar is free software etc/", вы увидите, что он все еще расширяется. Это очевидно более практично для примера [a-z]. – that other guy 16 November 2015 в 18:05
  • 4
    Я вижу, это имеет смысл для примера [a-z]. – ks1322 17 November 2015 в 09:42

двойная кавычка пользователя, чтобы получить точное значение. например:

echo "${var}"

, и он правильно прочитает ваше значение.

1
ответ дан vanishedzhou 19 August 2018 в 08:00
поделиться
0
ответ дан Charles Duffy 30 October 2018 в 20:11
поделиться