Операции подстановки текста, такие как «найти и заменить», распространены в любом текстовом редакторе. В этом разделе мы иллюстрируем, как SED выполняет замену текста. Ниже приведен синтаксис команды замещения.
[Address1 [, address2]] s / шаблон / замена / [флаги]
Здесь address1 и address2 — это соответственно начальный и конечный адреса, которые могут быть номерами строк или шаблонами. Оба эти адреса являются необязательными параметрами. Шаблон — это текст, который мы хотим заменить строкой замены. Кроме того, мы можем указать дополнительные флаги с помощью SED.
В файле books.txt мы использовали запятую (,) для разделения каждого столбца. Давайте используем вертикальную черту (|) для разделения каждого столбца. Для этого замените запятую (,) на вертикальную черту (|).
[jerry]$ sed 's/,/ | /' books.txt
Выполнив приведенный выше код, вы получите следующий результат:
1) Буря мечей | Джордж Р. Р. Мартин, 1216 2) Две башни | JRR Толкиен, 352 3) Алхимик | Пауло Коэльо, 197 4) Братство Кольца | JRR Толкиен, 432 5) Паломничество | Пауло Коэльо, 288 6) Игра престолов | Джордж Р. Р. Мартин, 864
Если вы внимательно наблюдаете, заменяется только первая запятая, а вторая остается такой, как есть. Зачем? Как только шаблон соответствует, SED заменяет его строкой замены и переходит на следующую строку. По умолчанию он заменяет только первое вхождение. Чтобы заменить все вхождения, используйте глобальный флаг (g) с SED следующим образом:
[jerry]$ sed 's/,/ | /g' books.txt
Выполнив приведенный выше код, вы получите следующий результат:
1) Буря мечей | Джордж Р. Р. Мартин | 1216 2) Две башни | JRR Толкиен | 352 3) Алхимик | Пауло Коэльо | 197 4) Братство Кольца | JRR Толкиен | 432 5) Паломничество | Пауло Коэльо | 288 6) Игра престолов | Джордж Р. Р. Мартин | +864
Теперь все вхождения запятых (,) заменены вертикальной чертой (|).
Мы можем дать команду SED выполнить замену текста только тогда, когда совпадение с шаблоном выполнено успешно. В следующем примере запятая (,) заменяется вертикальной чертой (|) только в том случае, если строка содержит шаблон «Паломничество».
[jerry]$ sed '/The Pilgrimage/ s/,/ | /g' books.txt
Выполнив приведенный выше код, вы получите следующий результат:
1) Буря мечей, Джордж Р. Р. Мартин, 1216 2) Две башни, JRR Толкиен, 352 3) Алхимик, Пауло Коэльо, 197 4) Братство Кольца, JRR Толкиен, 432 5) Паломничество | Пауло Коэльо | 288 6) Игра престолов, Джордж Р. Р. Мартин, 864
В дополнение к этому, SED может заменить конкретное вхождение шаблона. Заменим только второй экземпляр запятой (,) на вертикальную черту (|).
[jerry]$ sed 's/,/ | /2' books.txt
Выполнив приведенный выше код, вы получите следующий результат:
1) Буря мечей, Джордж Р. Р. Мартин | 1216 2) Две башни, Дж. Р. Р. Толкиен | 352 3) Алхимик Пауло Коэльо | 197 4) Братство Кольца, Дж. Р. Р. Толкиен | 432 5) Паломничество, Пауло Коэльо | 288 6) Игра престолов, Джордж Р. Р. Мартин | +864
В приведенном выше примере число в конце команды SED (или в месте флага) подразумевает второе вхождение.
САС предоставляет интересную особенность. После выполнения замены SED предоставляет возможность показывать только измененные строки. Для этого SED использует флаг p, который относится к печати. В следующем примере перечислены только измененные строки.
[jerry]$ sed -n 's/Paulo Coelho/PAULO COELHO/p' books.txt
Выполнив приведенный выше код, вы получите следующий результат:
3) Алхимик, Пауло Коэльо, 197 5) Паломничество, Пауло Коэльо, 288
Мы также можем сохранить измененные строки в другом файле. Для достижения этого результата используйте флаг w . В следующем примере показано, как это сделать.
[jerry]$ sed -n 's/Paulo Coelho/PAULO COELHO/w junk.txt' books.txt
Мы использовали одну и ту же команду SED. Давайте проверим содержимое файла junk.txt .
[jerry]$ cat junk.txt
Выполнив приведенный выше код, вы получите следующий результат:
3) Алхимик, Пауло Коэльо, 197 5) Паломничество, Пауло Коэльо, 288
Для выполнения замены без учета регистра используйте флаг i, который подразумевает игнорирование регистра. В следующем примере выполняется подстановка без учета регистра.
[jerry]$ sed -n 's/pAuLo CoElHo/PAULO COELHO/pi' books.txt
Выполнив приведенный выше код, вы получите следующий результат:
3) Алхимик, Пауло Коэльо, 197 5) Паломничество, Пауло Коэльо, 288
До сих пор мы использовали только символ передней косой черты (/) в качестве разделителя, но мы также можем использовать вертикальную черту (|), знак (@), знак вставки (^), восклицательный знак (!) В качестве разделителя. В следующем примере показано, как использовать другие символы в качестве разделителя.
Предположим, вам нужно заменить путь / bin / sed на /home/jerry/src/sed/sed-4.2.2/sed. Следовательно, ваша команда SED выглядит так:
[jerry]$ echo "/bin/sed" | sed 's/\/bin\/sed/\/home\/jerry\/src\/sed\/sed-4.2.2\/sed/'
Выполнив приведенный выше код, вы получите следующий результат:
/home/jerry/src/sed/sed-4.2.2/sed
Мы можем сделать эту команду более удобочитаемой и понятной. Давайте используем вертикальную черту (|) в качестве разделителя и посмотрим на результат.
[jerry]$ echo "/bin/sed" | sed 's|/bin/sed|/home/jerry/src/sed/sed-4.2.2/sed|'
Выполнив приведенный выше код, вы получите следующий результат:
/home/jerry/src/sed/sed-4.2.2/sed
В самом деле! Мы получили тот же результат, и синтаксис стал более читабельным. Точно так же мы можем использовать знак «@» (@) в качестве разделителя следующим образом:
[jerry]$ echo "/bin/sed" | sed 's@/bin/sed@/home/jerry/src/sed/sed-4.2.2/sed@'
Выполнив приведенный выше код, вы получите следующий результат:
/home/jerry/src/sed/sed-4.2.2/sed
В дополнение к этому мы можем использовать символ вставки (^) в качестве разделителя.
[jerry]$ echo "/bin/sed" | sed 's^/bin/sed^/home/jerry/src/sed/sed-4.2.2/sed^'
Выполнив приведенный выше код, вы получите следующий результат:
/home/jerry/src/sed/sed-4.2.2/sed
Мы также можем использовать восклицательный знак (!) В качестве разделителя следующим образом:
[jerry]$ echo "/bin/sed" | sed 's!/bin/sed!/home/jerry/src/sed/sed-4.2.2/sed!'
Выполнив приведенный выше код, вы получите следующий результат:
/home/jerry/src/sed/sed-4.2.2/sed
Обычно обратный слеш (/) используется в качестве разделителя, но иногда удобнее использовать другие поддерживаемые разделители с SED.
Создание подстроки
Мы узнали мощную команду замены. Давайте посмотрим, сможем ли мы найти подстроку из сопоставленного текста. Давайте разберемся, как это сделать с помощью примера.
Давайте рассмотрим следующий текст:
[jerry]$ echo "Three One Two"
Предположим, мы должны организовать это в последовательности. Значит, он должен сначала напечатать Один, затем Два и, наконец, Три. Следующий однострочник делает все необходимое.
echo "Three One Two" | sed 's|\(\w\+\) \(\w\+\) \(\w\+\)|\2 \3 \1|'
Обратите внимание, что в приведенном выше примере в качестве разделителя используется вертикальная черта (|).
В SED подстроки могут быть указаны с помощью оператора группировки, и перед ним должен стоять префикс с escape-символом, т. Е. \ ( И \) .
\ w — это регулярное выражение, которое соответствует любой букве, цифре или подчеркиванию, а «+» используется для соответствия более чем одному символу. Другими словами, регулярное выражение \ (\ w \ + \) соответствует одному слову из входной строки.
Во входной строке три слова разделены пробелом, поэтому есть три регулярных выражения, разделенных пробелом. Первое регулярное выражение хранит первое слово, т. Е. Три, второе хранит слово один , а третье хранит слово два
Эти подстроки обозначаются \ N, где N — номер подстроки. Следовательно, \ 2 печатает вторую подстроку, т.е. One; \ 3 печатает третью подстроку, т.е. Two; и \ 1 печатает первую подстроку, т.е. три
Давайте разделим эти слова запятыми (,) и соответствующим образом изменим регулярное выражение.
[jerry]$ echo "Three,One,Two" | sed 's|\(\w\+\),\(\w\+\),\(\w\+\)|\2,\3,\1|'
Выполнив приведенный выше код, вы получите следующий результат:
Один два три
Обратите внимание, что теперь в регулярном выражении есть запятая (,) вместо пробела.
Флаги замены строки (только GNU SED)
В предыдущем разделе мы видели несколько примеров команды замещения. GNU SED предоставляет некоторые специальные escape-последовательности, которые можно использовать в строке замены. Обратите внимание, что эти флаги замены строк специфичны для GNU и могут не работать с другими вариантами SED. Здесь мы обсудим флаги замены строк.
-
\ L: если в строке замены указано \ L, все оставшиеся символы слова после \ L обрабатываются строчными буквами. Например, символы «ULO» обрабатываются как строчные буквы.
\ L: если в строке замены указано \ L, все оставшиеся символы слова после \ L обрабатываются строчными буквами. Например, символы «ULO» обрабатываются как строчные буквы.
[jerry]$ sed -n 's/Paulo/PA\LULO/p' books.txt
Выполнив приведенный выше код, вы получите следующий результат:
3) Алхимик, Пауло Коэльо, 197 5) Паломничество, Пауло Коэльо, 288
-
\ u: Когда в строке замены указан \ u, он обрабатывает непосредственный символ после \ u как символ верхнего регистра. В следующем примере \ u используется перед символами «a» и «o». Следовательно, SED рассматривает эти символы как заглавные буквы.
\ u: Когда в строке замены указан \ u, он обрабатывает непосредственный символ после \ u как символ верхнего регистра. В следующем примере \ u используется перед символами «a» и «o». Следовательно, SED рассматривает эти символы как заглавные буквы.
[jerry]$ sed -n 's/Paulo/p\uaul\uo/p' books.txt
Выполнив приведенный выше код, вы получите следующий результат:
3) Алхимик, Пауло Коэльо, 197 5) Паломничество, Поло Коэльо, 288
-
\ U: Когда в строке замены указано \ U, все оставшиеся символы слова после \ U считаются заглавными.
\ U: Когда в строке замены указано \ U, все оставшиеся символы слова после \ U считаются заглавными.
[jerry]$ sed -n 's/Paulo/\Upaulo/p' books.txt
Выполнив приведенный выше код, вы получите следующий результат:
3) Алхимик, Пауло Коэльо, 197 5) Паломничество, Пауло Коэльо, 288
-
\ E: Этот флаг должен использоваться с \ L или \ U. Останавливает преобразование, инициированное флагом \ L или \ U. В следующем примере только первое слово заменяется заглавными буквами.
\ E: Этот флаг должен использоваться с \ L или \ U. Останавливает преобразование, инициированное флагом \ L или \ U. В следующем примере только первое слово заменяется заглавными буквами.
[jerry]$ sed -n 's/Paulo Coelho/\Upaulo \Ecoelho/p' books.txt
Выполнив приведенный выше код, вы получите следующий результат: