Использование echo или printf для вывода новой строки и возврата каретки в виде \n и \r

Оригинальный выпуск

Регулярное выражение не может быть указано с опцией -Fотносительно grep. Есть еще одна проблема, связанная с регулярным выражением. Если символ ^используется в качестве привязки к началу строки, он должен быть первым символом регулярного выражения.

prompt% cp -v input input.back
prompt% grep -e "$regex" input.back > output
prompt% grep -v "$regex" input.back > input

Регулярное выражение:Оригинальный постер не предоставил конкретных входных данных, поэтому трудно найти подходящее регулярное выражение.

Редактировать :, наконец, исходный постер предоставил образец входного файла.

Apple/One-plus/Samsung/Mi/Sony/_Nokia/
Apple/One-plus/Samsung/Mi/Lenovo/_Nokia/
Apple/One-plus/Samsung/Mi/HTC/OPPO/

Регулярное выражение:regex

regex='\([-[:alpha:]]\+\/\)\{5\}_Nokia\/'

Альтернативные решения

Подобные решения не рекомендуются новичкам, которые никогда не читали руководство по sed.

sed -n "/$regex/p;/$regex/d;w input" input.back > output

Грубо говоря,строки, соответствующие регулярному выражению, сохраняются в файле output, затем удаляются из соответствующего sed-буфера, а содержимое буфера записывается в файл input.

sed -i.back -e "/$regex/w output" -e "/$regex/d" input

Эти команды имеют небольшие различия, но вторая более удобна.

2
17.06.2021, 13:54
2 ответа

Реализация GNU printfили printf, встроенная в ksh93, zsh или bash, будет делать что-то подобное с printf %q, выводя строки, как если бы они заключались в кавычки $'...'ksh93, когда они содержат управляющие символы. например возврат каретки или перевод строки:

$ string=$'foo\rbar\n' ksh93 -c 'printf "%q\n" "$string"'
$'foo\rbar\n'
$ string=$'foo\rbar\n' zsh -c 'printf "%q\n" "$string"'
foo$'\r'bar$'\n'
$ string=$'foo\rbar\n' bash -c 'printf "%q\n" "$string"'
$'foo\rbar\n'
$ string=$'foo\rbar\n'; /usr/bin/printf "%q\n" "$string"
'foo'$'\r''bar'$'\n'

В оболочке zshвы также можете использовать флаг расширения параметра qqqq, чтобы безоговорочно использовать эти $'...'кавычки:

$ s1=$'\r\n' s2=foobar
$ print -rC1 -- ${(qqqq)s1} ${(qqqq)s2}
$'\r\n'
$'foobar'
2
28.07.2021, 11:24

Использование трассировки

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

x=$(printf a\\rb)
(set -x; LC_ALL=C; : "$x")

приводит к трассировке с использованием нотации $'…'в оболочках, которые ее поддерживают :например, ksh, mksh и bash all print

+ : $'a\rb'

Но другие оболочки, такие как dash и BusyBox,просто напечатайте символ возврата каретки в стандартную ошибку, что приведет к неоднозначному выводу на терминале, чего, как я понимаю, вы хотите избежать. Если это возможно, запустите скрипт в bash или (m )ksh (или zsh в режиме эмуляции sh )во время отладки.

Использование printf

Некоторые реализации printf имеют спецификатор q. %qпохож на %s, но заключает в кавычки некоторые символы таким образом, чтобы вывод можно было проанализировать обратно в оболочку. Результат также визуально однозначен, т.е. вкладки печатаются как \t. Реализация GNU printf также поддерживает %q.

LC_ALL=C printf %q\\n "$x"

В dash в Linux необходимо использовать внешнюю утилиту printf:/usr/bin/printf. В BusyBox эта функция недоступна.

Трубопровод через катушку

Многие реализации catмогут выводить непечатаемые -символы визуальным способом, например. вкладки ^I, а не куча пробелов. Обратите внимание, что это не однозначно :табуляция неотличима от двух символов ^I.

printf '%s\n' "$x" | cat -vet

Шестнадцатеричный дамп

Вы можете распечатать вывод с шестнадцатеричным дампом. Портативный способ сделать это с помощью od.

$ x=$(printf a\\tc\\rb); printf %s "$x" | od -tx1'
0000000 61 09 63 0d 62
0000005

Утилита BSDhexdump(hdдля краткости ), доступная в *BSD и дистрибутиве Linux, производном от Debian -, также выводит печатные символы, что удобнее.

$ x=$(printf a\\tc\\rb); printf %s "$x" | hd
00000000  61 09 63 0d 62                                    |a.c.b|
00000005

Популярная утилита xxd(, распространяемая вместе с Vim, но доступная в виде отдельного пакета в большинстве дистрибутивов ), имеет аналогичный формат вывода.

$ x=$(printf a\\tc\\rb); printf %s "$x" | xxd -g1
00000000: 61 09 63 0d 62                                   a.c.b

Трудный путь

Вы можете перевести все непечатаемые символы один за другим, используя sed. Обратите внимание, что для создания переносимого скрипта вам нужно фактически передать эти печатные символы в sed. Если sed вызывается из сценария оболочки, вы можете использовать printfдля создания сценария sed. Приведенный ниже сценарий выводит наиболее распространенные управляющие символы в виде экранирования обратной косой черты; добавьте больше, если хотите.

#!/bin/sh
export LC_ALL=C
sed_script=$(printf '
s/\\\\/\\\\\\\\/g
s/'\''/\\\\'\''/g
s/\a/\\\\a/g
s/\b/\\\\b/g
s/\t/\\\\t/g
s/\f/\\\\f/g
s/\r/\\\\r/g
s/\033/\\\\e/g
$!s/$/\\\\n/
')
quoted=$(printf %sa "$2" | sed "$sed_script" | tr -d '\n')
printf "%s=\$'%s'\n" "$1" "${quoted%a}"

Использование:quoted-dump x "$x"

1
28.07.2021, 11:24

Теги

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