У меня есть команда замены sed, которую я хотел бы сделать совместимой как с BSD, sed
так и с GNU sed
. Расширенные регулярные выражения не являются проблемой, поскольку в данном случае они мне не нужны. Моя главная проблема заключается в разнице в том, как эти два sed
s интерпретируют escape-последовательности символов взаменастроки. Моя строка замены содержит табуляции и символы новой строки, и я хотел бы, чтобы они были видны в командных строках для простоты обслуживания, однако BSD sed
не интерпретирует escape-последовательности и GNUsed
делает. Каков подходящий способ указания sed
интерпретировать эти escape-последовательности на BSD? Следующие два фрагмента олицетворяют мою проблему:
ГНУsed
echo ABC | sed 's/B/\n\tB\n'
урожайность
A
B
C
БСДsed
echo ABC | sed 's/B\n\tB\n'
урожайность
AntBnC
Очевидно, \n
и \t
не интерпретируются BSD как escape-последовательности.sed
Теперь, к моему вопросу. Согласно странице руководства BSD sed
:
Чтобы указать символ новой строки в строке замены, поставьте перед ним обратную косую черту.
Означает ли это, что мне нужно будет предшествоватьбуквальныйновая строка с помощью обратной косой черты? Каков подходящий способ указать, sed
как интерпретировать escape-последовательности, как \n
в тексте замены?
решение1
Вы можете использовать кавычки bash $'...'
для интерпретации экранированных символов перед передачей строки в sed
.
Из страницы руководства bash:
Words of the form $'string' are treated specially. The word
expands to string, with backslash-escaped characters replaced as
specified by the ANSI C standard. Backslash escape sequences, if
present, are decoded as follows:
\a alert (bell)
\b backspace
\e an escape character
\f form feed
\n new line
\r carriage return
\t horizontal tab
\v vertical tab
\\ backslash
\' single quote
\nnn the eight-bit character whose value is the octal
value nnn (one to three digits)
\xHH the eight-bit character whose value is the hexadeci-
mal value HH (one or two hex digits)
\cx a control-x character
The expanded result is single-quoted, as if the dollar sign had
not been present.
A double-quoted string preceded by a dollar sign ($) will cause
the string to be translated according to the current locale. If
the current locale is C or POSIX, the dollar sign is ignored. If
the string is translated and replaced, the replacement is double-
quoted.
решение2
Если вам нужно писать переносимые скрипты, вам следует придерживаться функций встандарт POSIX(также известная как Single Unix, также известная как Open Group Base Specification).Выпуск 7, он же POSIX-1.2008является новейшей версией, но многие системы еще не полностью ее внедрили.Выпуск 6, он же POSIX-1.2001в целом поддерживается всеми современными юниксами.
Всед, значение управляющих последовательностей, таких как \t
и \n
не является переносимым, за исключением того, что врегулярное выражение, \n
обозначает новую строку. В тексте замены для s
команды \n
непереносимо, но вы можете использовать последовательность обратная косая черта-новая строка для обозначения новой строки.
Портативный способ создания символа табуляции (или любого другого символа, выраженного в восьмеричной системе) — этоtr
. Сохраните символ в переменной оболочки и подставьте эту переменную во фрагмент sed.
tab=$(echo | tr '\n' '\t')
escape=$(echo | tr '\n' '\033')
embolden () {
sed -e 's/^/'"$escape"'[1m/' -e 's/$/'"$escape"'[0m/'
}
Еще раз обратите внимание, что в регулярных выражениях и в текстах замены переносы строк должны выражаться по-разному s
.
Вы можете использоватьawkВместо этого. Он допускает экранирование с помощью обратной косой черты, включая восьмеричные экранирования \ooo
, в каждом строковом литерале.
решение3
На этот вопрос уже ответили на Stack Overflow:
https://stackoverflow.com/questions/1421478/how-do-i-use-a-new-line-replacement-in-a-bsd-sed
Это практически то же самое, что сказал jw013.
Чтобы вставить буквальную табуляцию, введите ctrl+ VTab.