Странное поведение TR использующих диапазон

Alternate example for @lesmana solution, possibly simplified.
Provides logging to file if desired.
=====
$ cat z.sh
TEE="cat"
#TEE="tee z.log"
#TEE="tee -a z.log"

exec 8>&- 9>&-
{
  {
    {
      { #BEGIN - add code below this line and before #END
./zz.sh
echo ${?} 1>&8  # use exactly 1x prior to #END
      #END
      } 2>&1 | ${TEE} 1>&9
    } 8>&1
  } | exit $(read; printf "${REPLY}")
} 9>&1

exit ${?}
$ cat zz.sh
echo "my script code..."
exit 42
$ ./z.sh; echo "status=${?}"
my script code...
status=42
$
10
03.07.2018, 23:26
2 ответа

у вас есть файл с именем oв текущем каталоге

foo> ls
foo> echo "abcdefghijklmnopqrstuvwxyz1234567890"|tr -d [a-z]
1234567890
foo> touch o
foo> echo "abcdefghijklmnopqrstuvwxyz1234567890"|tr -d [a-z]
abcdefghijklmnpqrstuvwxyz1234567890

Оболочка расширит строку [a-z], если будет найдено совпадение.

Согласноman bash

это называется расширением имени пути.

Pathname Expansion
After word splitting, unless the -f option has been set, bash scans each word for the characters *, ?, and [.... (...)

bash выполнит расширение.

[...] Matches any one of the enclosed characters.

25
27.01.2020, 19:59

Что происходит

Оболочка (bash )видит аргумент [a-z]. Это подстановочный знак (a glob ), который соответствует любой строчной букве¹. Поэтому оболочка ищет имя файла, соответствующее этому шаблону. Есть три случая:

  • Ни один файл в текущем каталоге не имеет имени, состоящего из одной строчной буквы. Затем оболочка оставляет подстановочный шаблон без изменений, и trвидит аргументы -dи [a-z]. Это то, что происходит на большинстве ваших машин.
  • Один файл в текущем каталоге имеет имя, состоящее из одной строчной буквы. Затем оболочка расширяет шаблон до этого имени файла, и trвидит аргументы -dи имя файла. Это происходит на сервере, и соответствующий файл называется o, так как мы видим, что trудалил букву o.
  • Два или более файла в текущем каталоге имеют имя, состоящее из одной строчной буквы. Затем оболочка расширяет шаблон до списка совпадающих имен файлов и trвидит три или более аргументов:-dи имена файлов. Так как trожидает один аргумент после -d, он будет жаловаться.

Что ты должен был сделать

Если в аргументе команды есть специальные символы, их необходимо экранировать. Поместите аргумент в одинарные кавычки'…'(это самый простой способ, есть и другие ). Внутри одинарных кавычек все символы обозначают сами себя, кроме самой одинарной кавычки. Если внутри аргумента есть одинарная кавычка, замените ее на'\''.

tr -d '[a-z]'

Однако заметьте, что это, вероятно, не то, что вы имели в виду! Это указывает trудалить строчные буквы и квадратные скобки. Это эквивалентно tr -d ']a-z[', tr '[]a-z'и т. д. Чтобы удалить строчные буквы, используйте

tr -d a-z

Аргументом trявляется набор символов.Вы заключаете в скобки набор символов в регулярном выражении или шаблоне подстановочных знаков, чтобы указать, что это набор символов. Но trработает с одним символом за раз. Его аргументы командной строки — это то, что вы поместили в скобки .

Скобки нужны для обозначения классов символов . В регулярном выражении вы используете скобки внутри скобок, чтобы указать класс символов, например. [[:lower:]]*соответствует любому количеству строчных букв, [[:lower:]_]*соответствует любому количеству строчных букв и знаков подчеркивания. В аргументе trвам нужен набор без окружающих скобок, поэтому tr -d '[:lower:]'удаляет строчные буквы, tr -d '[:lower:]_'удаляет строчные буквы и знаки подчеркивания и т. д.

¹В некоторых локалях он может соответствовать другим символам .

8
27.01.2020, 19:59

Теги

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