Sed - zastąpić postać w dopasowanej linii na miejscu?


21

W pliku zawierającym takie linie:

# lorem ipsum blah variable

Chciałbym usunąć #(komentarz) znak w tym samym wierszu, który zawiera określony ciąg znaków. Czy sedto jest dobre?

Walczę o to, aby to warunkowe działanie działało. Mam na to „niezdarny” sposób; Mogę znaleźć pasujący numer linii za pomocą awklub, seda następnie użyć tego numeru w osobnym sedpoleceniu, ale uważam, że można to zrobić w znacznie lepszy sposób.

Odpowiedzi:


36

Użyj łańcucha, którego szukasz, jako selektora linii, które mają być obsługiwane:

sed '/ipsum/s/#//g'

/ipsum/wybiera wiersze zawierające „ipsum” i tylko w tych wierszach wykonywane są następujące polecenia. Możesz użyć nawiasów klamrowych, aby uruchomić więcej poleceń

/ipsum/{s/#//g;s/@/-at-/g;}

4
Zgadzam się; to najlepsza odpowiedź (choć nie jedyna). Komentarze: (1) 's/#//g'usunie wszystkie te #znaki w linii. Jeśli nie tego chcesz, usuń g(co oznacza „globalny”). (2) Aby edytować plik na miejscu (zgodnie z pytaniem w pytaniu), użyj sed -i.
G-Man mówi „Przywróć Monikę”

2
(3) W przypadku rzeczywistych sytuacji, jeśli chcesz cofnąć komentarz do linii, możesz użyć sed -i '/ipsum/s/#[[:space:]]*//', aby pozbyć się spacji i tabulatorów bezpośrednio po #. (4) Możesz również rozważyć sprawdzenie, czy #jest to pierwszy niepusty znak w linii. Bieżące polecenie spowoduje usunięcie #z linii prompt "Enter # of ipsums:".
G-Man mówi „Przywróć Monikę”

1
@ G-Man - świetny dodatek! Do drugiego pt (wiodącej przestrzeni), co z: sed -i '/ipsum/s/^#[[:space:]]*//'?! ( ^oznacza początek linii, $koniec linii) - przynajmniej w gnu sed ...
Jeremy Davis,

1
@JeremyDavis: Tak, mógłby zakotwiczyć regex do początku wiersza z ^, ale to byłoby źle. Często komentuję wcięty kod, umieszczając #bezpośrednio przed nim, więc #jest wcięty. Wątpię, że jestem jedyną osobą, która to robi.
G-Man mówi „Przywróć Monikę”

1
@ G-Man - no tak, oczywiście! Dzięki, nie zastanawiałem się nad tym. Tak, że chcemy także, aby sprawdzić spacji pomiędzy ^i #tak coś bardziej jak to: /ipsum/{/^[[:space:]]*#/s/#[[:space:]]*//}. Chociaż nawet wtedy, w zależności od tego, gdzie #jest, może nadal powodować problemy (np. W językach, które używają wcięć / separacji białych znaków).
Jeremy Davis,

7
$ cat input.txt
# lorem ipsum blah variable
# lorem ipsum blat variable
# lorem ipsum blow variable
# lorem ipsum blip variable
# lorem ipsum blue variable

następnie:

$ sed 's|# \(.*blue.*\)|\1|' input.txt

daje:

# lorem ipsum blah variable
# lorem ipsum blat variable
# lorem ipsum blow variable
# lorem ipsum blip variable
lorem ipsum blue variable

Działa w następujący sposób:

sMówi sed, że powinien on zastąpić co wyrażenie regularne znajdzie.

Wzór jest następujący # \(.*blue.*\): Znajdź skrót, a następnie spację. Nawias kwadratowy ( \() rozpoczyna grupowanie. .*blue.*to słowo bluez czymkolwiek przed i po. Następny nawias kwadratowy ( \)) zamyka grupowanie.

Zastąpienie stanowi \1odniesienie wsteczne do treści pierwszego przedziału grupowania.


3

Możesz używać Vima w trybie Ex:

ex -sc '/ipsum/s/#//|x' file
  1. s zastąpić

  2. x Zapisz i zamknij


To fajnie. Nie wiedziałem o tym! TBH, nie jestem pewien, czy to najlepsza odpowiedź na to pytanie (IMO wiodąca odpowiedź sed to jedna), ale wciąż jest bardzo fajna! Dzięki za wysłanie.
Jeremy Davis,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.