Какие символы мне нужно избегать при использовании sed в сценарии sh?

Возьмите следующий скрипт:

#! /Bin /ш
sed 's /(127 \ .0 \ .1 \ .1) \ s /\ 1 /' [некоторый файл]

Если я попытаюсь запустить это в sh (dash здесь), он будет терпеть неудачу из-за скобок, которые должны быть экранированы. Но я не должен избегать обратных косых черт (между октетами или в \ s или \ 1)). Какое правило здесь? Как насчет того, когда мне нужно использовать {...} или [...]? Есть ли список того, что я делаю, и вам не нужно бежать?

201 голос | спросил detly 28 FebruaryEurope/MoscowbTue, 28 Feb 2012 08:42:16 +0400000000amTue, 28 Feb 2012 08:42:16 +040012 2012, 08:42:16

3 ответа


231

Здесь есть два уровня интерпретации: оболочка и sed.

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

Sed использует основные регулярные выражения . В BRE для того, чтобы они обрабатывались буквально, символы $. * [\] ^ должны быть процитированы, предшествуя им обратным слэшем, за исключением внутренних наборов символов ([â € |]). Буквы, цифры и () {} +? | не должны указываться (вы можете уйти от цитирования некоторых из них в некоторых реализациях). Последовательности \ (, \), \ n и в некоторых реализациях \ {, \ }, \ +, \?, \ | и другие символы обратной косой черты + alphanumerics имеют особые значения. Вы можете обойтись без цитирования $ ^] в некоторых позициях в некоторых реализациях.

Кроме того, вам нужна обратная косая черта перед /, если она появится в регулярном выражении вне выражений скобок. Вы можете выбрать альтернативный символ как разделитель, записав, например, s ~ /dir ~ /replacement ~ или \ ~ /dir ~ p; вам понадобится обратная косая черта перед разделителем, если вы хотите включить его в BRE. Если вы выберите персонажа, который имеет особое значение в BRE, и вы хотите включить его в буквальном смысле, вам понадобятся три обратные косые черты; Я не рекомендую это, так как он может вести себя по-разному в некоторых реализациях.

В двух словах, для sed 's /â € | /â € | /':

  • Напишите регулярное выражение между одинарными кавычками.
  • Используйте '\' ', чтобы получить одну цитату в регулярном выражении.
  • Поставьте обратную косую черту перед $. * /[\] ^ и только те символы (но не внутренние выражения).
  • Внутри выражения скобки, для -, которое нужно обрабатывать буквально, убедитесь, что оно первое или последнее ([abc -] или [- abc], а не [a-bc]).
  • Внутри выражения скобки, для ^, которое нужно обрабатывать буквально, сначала убедитесь, что оно not (используйте [abc ^], not [^ а]).
  • Чтобы включить ] в список символов, сопоставляемый выражением скобки, сделайте его первым символом (или первым после ^ для отрицаемого набора): [] abc] или [^] abc] (не [abc]] и [abc \]]).

В тексте замены:

  • & и \ необходимо процитировать, предшествуя им обратным слэшем, как и разделитель (обычно /) и новые строки.
  • \, за которым следует цифра, имеет особое значение. \, за которым следует буква, имеет особые значения (специальные символы) в некоторых реализациях и \, за которыми следуют другие символы: \ c или < code> c в зависимости от реализации.
  • С одинарными кавычками вокруг аргумента (sed /â € | /â € | /') используйте ' \ '', чтобы поместить одну цитату в текст замены.

Если регулярное выражение или текст замены поступает из командной строки, помните, что

  • Регулярное выражение - это BRE, а не буквальная строка.
  • В регулярном выражении новая строка должна быть выражена как \ n (которая никогда не будет соответствовать, если у вас нет другого кода sed, добавляющего символы новой строки в пространство шаблонов). Но учтите, что он не будет работать внутри выражений скобок с некоторыми реализациями sed.
  • В тексте замены &, \ и новые строки должны быть указаны.
  • Разделитель должен быть указан (но не внутри выражений в скобках).
  • Используйте двойные кавычки для интерполяции: sed -e "s /$ BRE /$ REPL /".
ответил Gilles 29 FebruaryEurope/MoscowbWed, 29 Feb 2012 05:06:45 +0400000000amWed, 29 Feb 2012 05:06:45 +040012 2012, 05:06:45
40

Проблема, с которой вы столкнулись, связана не с интерпретацией оболочки и с экранированием оболочки - это потому, что вы пытаетесь использовать расширенный синтаксис регулярных выражений без передачи sed -r или - regexp-extended.

Измените строку sed из

sed 's /(127 \ .0 \ .1 \ .1) \ s /\ 1 /' [некоторый файл]

to

sed -r 's /(127 \ .0 \ .1 \ .1) \ s /\ 1 /' [некоторый файл]

, и он будет работать, как я полагаю, вы намерены.

По умолчанию sed использует основные регулярные выражения (думаю, стиль grep), для чего потребуется следующий синтаксис:

sed '/\ (127 \ .0 \ .1 \ .1 \) [\ t] /\ 1 /' [некоторый файл]
ответил R Perrin 29 FebruaryEurope/MoscowbWed, 29 Feb 2012 06:56:20 +0400000000amWed, 29 Feb 2012 06:56:20 +040012 2012, 06:56:20
13

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

Итак, если вы хотите, чтобы sed увидел s /\ (127 \ .0 \ .1 \ .1 \) \ s /\ 1 /, оставьте вокруг него одинарные кавычки, и оболочка не будет коснитесь круглых скобок или обратных косых черт. Если вам нужно интерполировать переменную оболочки, поместите только эту часть в двойные кавычки. Например.

sed 's /\ (127 \ .0 \ .1 \ .1 \) /' "$ ip" '/'

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

ответил Kyle Jones 28 FebruaryEurope/MoscowbTue, 28 Feb 2012 09:58:46 +0400000000amTue, 28 Feb 2012 09:58:46 +040012 2012, 09:58:46

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

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132