Як знайти та замінити рядок без використання команди Sed?


16

Як ми всі знаємо, sedє дуже ефективним , щоб знайти і замінити рядок, наприклад , знахідка «а» і замінити його на «Комерсант»: sed 's/a/b/g'.

Чи можливо це зробити за допомогою іншого скрипта команди або оболонки замість sed?

Це для обрізаних систем Linux для телевізора, які не мають sedкоманди. Тому я маю використовувати інші команди або скрипти замістьsed 's/a/b/g'. –


Насправді, це просто регулярне вираження підстановки. Будь-який інструмент або мову , здатний обробляти такі речі будуть мати можливість робити те ж саме, але з різним синтаксисом: $var=~s/a/b/g, gsub(/a/,"b",var), var.gsub(/a/,'b'), var.replace(/a/g,'b'), preg_replace("/a/","b",$var), regsub -all a b $var. Окрім цього, багато інструментів та мов також можуть замінити звичайний текстовий рядок. Тож ваше запитання якось широке.
манатура

1
Чому? Яку проблему ви намагаєтеся вирішити?
Жил "ТАК - перестань бути злим"

Обрізана система Linux для телевізора не командує. Тому я повинен використовувати іншу команду чи скрипт, а не sed 's / a / b / g'.
binghenzq

Відповіді:


12

Так, існує безліч способів зробити це. Ви можете використовувати awk, perlабо bashзробити ці заходи , а також. Взагалі, хоча sedце, мабуть, найбільш підходящий інструмент для виконання таких завдань.

Приклади

Скажіть, я маю ці зразкові дані у файлі data.txt:

foo bar 12,300.50
foo bar 2,300.50
abc xyz 1,22,300.50

awk

$ awk '{gsub("foo", "foofoofoo", $0); print}' data.txt 
foofoofoo bar 12,300.50
foofoofoo bar 2,300.50
abc xyz 1,22,300.50

Perl

$ perl -pe "s/foo/foofoofoo/g" data.txt 
foofoofoo bar 12,300.50
foofoofoo bar 2,300.50
abc xyz 1,22,300.50

Вбудоване редагування

Наведені вище приклади також можуть безпосередньо змінювати файли. Приклад Перла - тривіальний. Просто додайте -iперемикач.

$ perl -pie "s/foo/foofoofoo/g" data.txt 

Бо awkце трохи менш прямо, але так само ефективно:

$ { rm data.txt && awk '{gsub("foo", "foofoofoo", $0); print}' > data.txt; } < data.txt

Цей метод створює підрозділ із дужками '{...} `, де файл перенаправляється в нього через це:

$ { ... } < data.txt

Після того, як файл буде перенаправлений в підрозділ, він видаляється, а потім awkзапускається проти вмісту файла, який був прочитаний в під оболонки STDIN. Потім цей вміст обробляється awkта виписується назад до того самого імені файлу, який ми щойно видалили, фактично замінивши його.


Дякую за вашу відповідь, і я спробую це наступного робочого дня. Але я не впевнений, чи спрацює це, тому що якась команда може не існувати в обрізаних linux системах телевізора, як-от "sed'.Так я все ще хочу використовувати команду" знайти " , 'grep' тощо, щоб вирішити це.
binghenzq

@binghenzq - я додав приклади, які редагують файл вбудований.
slm

-1 Я рідко виступаю проти, але в цьому випадку питання питання здавалося більш простим методом, ніж інші більш / менш складні і, ймовірно, також залежні. Якби питання стосувалося альтернатив для встановлення повноцінного * nix-машини, я, мабуть, оцінив +1 інакше гарною відповіддю.
Майкл Дюрант

@MichaelDurrant - Я щойно додав ті вишукані вбудовані редагування, коли операційна програма попросила їх. Також ОП встановив вимогу НЕ використовувати sedне I. Sed - це відповідний інструмент для заміни, такий як цей, і він, очевидно, просить краще зрозуміти ролі цих інструментів, тому показувати комусь ці речі, хоч і погані, є надзвичайно освіченими в демонстрації їм чому. Занадто багато разів ppl у знанні просто кажуть "не роби цього", не пояснюючи чому, так що я. Але дякую, що принаймні залишив коментар щодо того, чому ти DV.
slm

Звичайно, я вважав, що це чудова відповідь у всіх інших аспектах. так, я ненавиджу -1, не маючи пояснень.
Майкл Дюрант

13

Класична альтернатива заміни однієї літери - це trкоманда, яка повинна бути доступна майже в будь-якій системі:

$ echo "foobar" | tr a b   
foobbr

trкраще, ніж sedдля цього насправді, оскільки використовувати sed(не кажучи вже perlабо awk) для заміни однієї літери - це як використовувати кувалду для вбивання мухи.

grep не призначений для цього, він не змінює свій вхід, він лише здійснює пошук через нього.

Крім того, ви можете використовувати можливості заміщення деяких оболонок. Тут , використовуючи ksh, zshабо bashсинтаксис:

$ foo="foobar"
$ echo "${foo//a/b}"
foobbr

Ми можемо дати вам більш конкретні відповіді, якби ви точно пояснили, яку проблему ви намагаєтеся вирішити.


Чи є можливість ігнорувати випадок у справі ${foo//a/b}?
АлікЕльзін-кілака

@ AlikElzin-kilaka Боюся, що ні. Ви повинні будете використовувати що - то більш складне , як, наприклад: echo "$foo" | sed 's/a/b/iчи дати клас символів: echo ${foo//[aA]/b}.
terdon

4

Ви можете використовувати Vim в режимі Ex:

ex -s -c '%s/a/b/g|x' file
  1. % виберіть усі рядки

  2. s замінник

  3. g глобальна заміна

  4. x зберегти і закрити


щиро дякую. просто додати, -c прапор - це виконати команду, коли розпочнеться редагування (оскільки колишній є редактором), а прапор -s - або режим скрипту, який відключає зворотній зв'язок, або, як дехто хоче сказати слайд-режим. ref для отримання додаткової інформації: ex-vi.sourceforge.net/ex.html
Jimmy MG Lim

3

Якщо ви працюєте з файлом, а не потоком, ви можете використовувати стандартний текстовий редактор ed:

printf '%s\n' ',s/a/b/g' w q | ed file.txt

Це має бути доступне на будь-якому * nix. Кома ',s/a/b/g'вказує edпрацювати в кожному рядку (ви також можете використовувати %, який буде більш відомим, якщо ви звикли до vim), а решта - це стандартний пошук і заміна. wкаже йому написати (зберегти) файл, qпідказує йому вийти.

Зауважте, що на відміну від -iопції sed (і подібних варіантів інших інструментів), це насправді редагує файл на місці, а не обман з тимчасовими файлами.

Я не думаю, що це можливо зробити так, щоб це працювало з потоками, але тоді я насправді не знаю багато про що, edі я не здивуюсь, якщо він насправді має таку можливість (філософія Unix є тим, що вона є).


2

Використовуючи команду предка (що -sозначає тихо (беззвучне) і кома перед командами означає виконання у всіх рядках):

Просто друк на STDOUT :

ed -s file <<!
,s/a/b/g
,p
q
!

заміна на місці:

ed -s file <<!
,s/a/b/g
w
q
!
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.