Jak usunąć resztę każdego wiersza po określonym wzorcu lub ciągu w pliku?

21

Załóżmy, że mam listę adresów URL w pliku tekstowym:

google.com/funny
unix.stackexchange.com/questions
isuckatunix.com/ireallydo

Chcę usunąć wszystko, co następuje po „.com”.

Oczekiwane rezultaty:

google.com
unix.stackexchange.com
isuckatunix.com

próbowałem

sed 's/.com*//' file.txt 

ale to też zostało usunięte .com.

Koshur
źródło
Czy jest jakiś konkretny powód, dla którego chcesz szukać .comtylko zamiast usuwać wszystko po pierwszej /postaci i włącznie z nią ? Co jeśli masz adres URL taki jak en.wikipedia.org/wiki/Ubuntuna liście?
Bajt Dowódca

Odpowiedzi:

17

Aby jawnie usunąć wszystko, co następuje po „.com”, po prostu zmodyfikuj istniejące rozwiązanie sed, aby zamienić „.com (cokolwiek)” na „.com”:

sed 's/\.com.*/.com/' file.txt

Poprawiłem twoje wyrażenie regularne, aby uciec od pierwszego okresu; inaczej pasowałoby do czegoś w stylu „thisiscommon.com/something”.

Pamiętaj, że możesz dodatkowo zakotwiczyć wzór „.com” za pomocą ukośnika, aby nie przypadkowo przyciąć coś takiego jak „sub.com.domain.com/foo”:

sed 's/\.com\/.*/.com/' file.txt
Jeff Schaller
źródło
9

Możesz użyć awkseparatora pól ( -F) w następujący sposób:

$ cat file
google.com/funny
unix.stackexchange.com/questions
isuckatunix.com/ireallydo

$ cat file | awk -F '\\.com' '{print $1".com"}'
google.com
unix.stackexchange.com
isuckatunix.com

Wyjaśnienie:

NAME
       awk - pattern scanning and processing language

-F fs
       --field-separator fs
              Use fs for the input field separator (the value of the FS predefined variable).

Jak chcesz usunąć wszystkie rzeczy po .com, -F '.com'oddziela linię od .comi print $1daje wynik tylko część wcześniejszą .com. Tak, $1".com"dodaje .comi daje oczekiwany wynik.

Pandya
źródło
Dlaczego nie tylko /jako FS i wziąć pierwsze pole?
heemayl
1
@ Pandya: To nie działa z ciągiem jakacomercial.com/asdsad
cuonglm,
@cuonglm Dzięki za wskazanie. Poprawiona odpowiedź
Pandya
4

Najlepszym narzędziem do nieinteraktywnej edycji plików w miejscu jest ex.

ex -sc '%s/\(\.com\).*/\1/ | x' file.txt

Jeśli używałeś vii kiedykolwiek wpisałeś polecenie zaczynające się od dwukropka :, użyłeś polecenia ex. Oczywiście wiele bardziej zaawansowanych lub „fantazyjnych” poleceń, które można wykonać w ten sposób, są rozszerzeniami Vima (np. :bufdo) I nie są zdefiniowane w specyfikacjach POSIXex , ale specyfikacje te pozwalają na naprawdę zadziwiający stopień mocy i elastyczności w trybie niewizualnym edycja tekstu (interaktywna lub automatyczna).

Powyższe polecenie składa się z kilku części.

-swłącza tryb cichy, aby przygotować się exdo użycia wsadowego. (Pomiń komunikaty wyjściowe i in.)

-cokreśla polecenie do wykonania po file.txtotwarciu pliku ( w tym przypadku) w buforze.

%jest specyfikatorem adresu równoważnym 1,$— oznacza to, że następujące polecenie jest stosowane do wszystkich linii bufora.

sto polecenie zastępcze, które prawdopodobnie już znasz. Jest powszechnie używany vii ma zasadniczo identyczne funkcje jak spoleceniesed , chociaż niektóre zaawansowane funkcje wyrażenia regularnego mogą się różnić w zależności od implementacji. W tym przypadku z „.com” do końca wiersza zastępuje się tylko „.com”.

Pionowy pasek oddziela sekwencyjne polecenia do wykonania. W wielu (większości) eximplementacjach możesz również użyć dodatkowej -copcji, na przykład:

ex -sc '%s/\(\.com\).*/\1/' -c x file.txt

Nie jest to jednak wymagane przez POSIX.

Do xwyjścia polecenia, po zapisaniu zmian w pliku. W przeciwieństwie do tego, wqco oznacza „zapisz i wyjdź”, xzapisuje do pliku tylko wtedy, gdy bufor został edytowany. Dlatego jeśli plik nie zostanie zmieniony, znacznik czasu zostanie zachowany.

Dzika karta
źródło
1
+1 za użycie byłego
Jeffa Schallera
1
Nie edytuje się w miejscu. Przynajmniej nie robi nic więcej niż sedfałszywy -i Gnu . Odczytuje / zapisuje w buforach na dysku. Sprawdź sam w / ex -ri preservepolecenie.
mikeserv
@mikeserv Jakie jest preservepolecenie?
Mateen Ulhaq
2

Bardzo szybki, prosty i brudny sposób na python:

#!/usr/bin/env python
import sys
with open( sys.argv[1]  ) as file:
    for line in file:
        print line.split("/")[0]

Przykładowy przebieg

skolodya@ubuntu:$ chmod +x removeStrings.py                                   

skolodya@ubuntu:$ ./removeStrings.py strings.txt                              
google.com
unix.stackexchange.com
isuckatunix.com


skolodya@ubuntu:$ cat strings.txt                                             
google.com/funny
unix.stackexchange.com/questions
isuckatunix.com/ireallydo
Sergiy Kolodyazhnyy
źródło
2
Czy mogę podać powód odrzucenia?
Sergiy Kolodyazhnyy
3
Działa, ale to nie obchodzi .com, po prostu usuwa wszystko, zaczynając od pierwszego /w linii. (co jest moim zdaniem nawet lepszym podejściem!)
Bajt Dowódca
1
@ByteCommander dokładnie w porządku! Jeśli nazwa domeny to .net, w innych podejściach część, która pojawia się po domenie i rozszerzeniu, nie zostanie usunięta, więc bezpieczniej jest użyć jej /jako separatora.
Sergiy Kolodyazhnyy
+1 za odpowiedź i komentarze, które sprawiają, że czuję się jak na AskUbuntu.com: D
WinEunuuchs2Unix