Команда tr: странное поведение с | а также \ - PullRequest
0 голосов
/ 07 мая 2018

Допустим, у меня есть файл test.txt с содержимым:

+-foo.bar:2.4
|    bar.foo:1.1:test
\|  hello.goobye:3.3.3
   \|+- baz.yeah:4

Я хочу использовать команду tr, чтобы удалить все экземпляры следующего набора символов:

{' ', '+', '-', '|', '\'}

Провел довольно обширное исследование по этому вопросу, но не нашел четких / кратких ответов. Это команда, которая работает:

ввод:

cat test.txt | tr -d "[:blank:]|\\\+-"

выход:

foo.bar:2.4
bar.foo:1.1:test
hello.goobye:3.3.3
baz.yeah:4

Я экспериментировал со многими комбинациями этого набора и обнаружил, что '-' трактуется как индикатор диапазона (как ... [a-z]) и поэтому должен быть поставлен в конце. Но у меня есть два основных вопроса:

1) Почему обратный слеш должен быть дважды экранирован, чтобы быть включенным в набор?

2) Почему стоит ставить '|' в конце строки set заставить программу tr удалить все в файле, кроме завершающих символов новой строки?

Ответы [ 2 ]

0 голосов
/ 08 мая 2018

Другой подход заключается в определении разрешенных символов

$ tr -cd '[:alnum:]:.\n' <file

foo.bar:2.4
bar.foo:1.1:test
hello.goobye:3.3.3
baz.yeah:4

или, возможно, удалить все префиксы, не содержащие слов

$ sed -E 's/\W+//' file
0 голосов
/ 07 мая 2018

Как это:

tr -d '\-|\\+[:blank:] ' < file

Вы должны экранировать -, потому что он используется для обозначения диапазонов символов, таких как:

tr -d '1-5'

и, следовательно, должен быть сброшен, если вы имеете в виду буквальный дефис. Вы также можете положить его в конце. (узнал что, спасибо! :))

Кроме того, \ необходимо экранировать, когда вы имеете в виду литерал \, поскольку он имеет особое значение, необходимое для escape-последовательностей.

Остальные символы не должны быть экранированы.


Почему в вашем примере \ нужно дважды избежать?

Это потому, что вы используете строку "" (двойные кавычки) для цитирования набора символов. Строка в двойных кавычках будет интерпретироваться оболочкой, а \\ в строке в двойных кавычках означает литерал \. Попробуйте:

echo "\+"
echo "\\+"
echo "\\\+"

Чтобы избежать двойного выхода из \, вы можете просто использовать одинарные кавычки, как в моем примере выше.


Почему ставится '|' в конце установленной строки заставить программу tr удалять все в файле, кроме завершающих символов новой строки?

После комментария CharlesDuffy , имеющего | в конце, также означает, что у вас не было экранированного - не в конце, что означает, что он описывал диапазон символов, от которых зависит реальный диапазон позиция у вас была в наборе.

...