Nie chciwy (niechętnie) dopasowanie wyrażenia regularnego w sed?


406

Próbuję użyć sed do czyszczenia linii adresów URL w celu wyodrębnienia samej domeny.

Więc z:

http://www.suepearson.co.uk/product/174/71/3816/

Chcę:

http://www.suepearson.co.uk/

(z ukośnikiem końcowym lub bez niego, to nie ma znaczenia)

Próbowałem:

 sed 's|\(http:\/\/.*?\/\).*|\1|'

i (uciekając przed niechcianym kwantyfikatorem)

sed 's|\(http:\/\/.*\?\/\).*|\1|'

ale nie mogę sprawić, żeby nie chciwy kwantyfikator ( ?) działał, więc zawsze kończy się to dopasowaniem całego łańcucha.


54
Dodatkowa uwaga: jeśli ograniczysz wyrażenia regularne za pomocą „|”, nie musisz uciekać od „/”. W rzeczywistości większość ludzi ogranicza znak „|” zamiast „/”, aby uniknąć „płotu”.
AttishOculus,

12
@AttishOculus Pierwszym znakiem po 's' w wyrażeniu zastępczym w sed jest ogranicznik. Stąd ^ foo ^ bar ^ 'lub' s! Foo! Bar! ' też działają
Squidly

1
W przypadku rozszerzonego wyrażenia regularnego użyj sed -E 's.... Nadal nie ma niechętnego operatora.
Ondra Žižka

Nie odpowiedź na tytuł pytania, ale w tym konkretnym przypadku proste cut -d'/' -f1-3prace.
Petr Javorik

Odpowiedzi:


421

Ani podstawowy, ani rozszerzony refiks Posix / GNU nie rozpoznaje niepochodnego kwantyfikatora; potrzebujesz późniejszego wyrażenia regularnego. Na szczęście wyrażenie regularne Perla dla tego kontekstu jest dość łatwe do uzyskania:

perl -pe 's|(http://.*?/).*|\1|'

12
Aby to zrobić, użyj opcji -pi -e.
reallynice

11
Jasne, nie mogę uwierzyć, że zadziałało :-) Jedyne, co jest do bani, to teraz mój skrypt ma zależność od Perla :-( Na plus, praktycznie każda dystrybucja Linuksa ma już Perla, więc prawdopodobnie nie jest to problem :-)
Freedom_Ben

6
@Freedom_Ben: IIRC perljest wymagane przez POSIX
MestreLion

4
@ dolphus333: „Ani podstawowy, ani rozszerzony refiks Posix / GNU nie rozpoznaje niepochodnego kwantyfikatora” oznacza „nie można używać niepochodnego kwantyfikatora w sed”.
chaos

3
@ Sérgio to sposób wykonania żądanej czynności, co jest niemożliwe sed, przy użyciu składni w zasadzie identycznej jak w przypadkused
chaosu

250

W tym konkretnym przypadku możesz wykonać zadanie bez użycia wyrażenia chciwego.

Spróbuj tego niechcianego wyrażenia regularnego [^/]*zamiast .*?:

sed 's|\(http://[^/]*/\).*|\1|g'

3
Jak sprawić, by sed match nie był chciwy, używając tej techniki?
user3694243,

6
Niestety nie możesz; patrz odpowiedź chaosu .
Daniel H

Wielkie dzięki ... ponieważ Perl nie jest już domyślną bazą instalacyjną w wielu dystrybucjach Linuksa!
st0ne


@DanielH W rzeczywistości możliwe jest dopasowanie wyrażeń niepotrzebnie za pomocą tej techniki zgodnie z żądaniem. Napisanie któregokolwiek wzoru z wystarczającą precyzją może wymagać trochę bólu. Na przykład podczas analizowania przypisania klucz-wartość w zapytaniu adresu URL może być konieczne wyszukanie przypisania za pomocą ([^&=#]+)=([^&#]*). Zdarzają się przypadki, które na pewno nie działają w ten sposób, np. Podczas analizowania adresu URL dla części hosta i nazwy ścieżki z końcowym ukośnikiem, który zakłada się opcjonalnie, aby został wykluczony z przechwytywania:^(http:\/\/.+?)/?$
Thomas Urban

121

W przypadku sed zwykle wdrażam niepochodne wyszukiwanie, szukając czegokolwiek oprócz separatora aż do separatora:

echo "http://www.suon.co.uk/product/1/7/3/" | sed -n 's;\(http://[^/]*\)/.*;\1;p'

Wynik:

http://www.suon.co.uk

to jest:

  • nie wysyłaj -n
  • wyszukaj, dopasuj wzór, zamień i wydrukuj s/<pattern>/<replace>/p
  • ;zamiast tego użyj separatora poleceń wyszukiwania, /aby ułatwić pisanies;<pattern>;<replace>;p
  • pamiętaj dopasowanie między nawiasami \(... \), później dostępne za pomocą \1, \2...
  • mecz http://
  • po którym następuje cokolwiek w nawiasach [], [ab/]oznaczałoby albo aalbo balbo/
  • pierwszy ^w []środkach not, a następnie wszystko oprócz rzeczy w[]
  • więc [^/]oznacza nic oprócz /charakteru
  • *jest powtarzanie poprzedniej grupy, co [^/]*oznacza znaki oprócz /.
  • do tej pory sed -n 's;\(http://[^/]*\)oznacza wyszukiwanie i zapamiętywanie, http://po których następują dowolne postacie oprócz /i pamiętanie tego, co znalazłeś
  • chcemy szukać do końca domeny, więc zatrzymaj się na następnej, /więc dodaj kolejną /na końcu: sed -n 's;\(http://[^/]*\)/'ale chcemy dopasować resztę wiersza po domenie, więc dodaj.*
  • teraz dopasowanie zapamiętane w grupie 1 ( \1) jest domeną, więc zamień dopasowaną linię na rzeczy zapisane w grupie \1i wydrukuj:sed -n 's;\(http://[^/]*\)/.*;\1;p'

Jeśli chcesz dołączyć ukośnik odwrotny również po domenie, dodaj jeszcze jeden ukośnik w grupie, aby zapamiętać:

echo "http://www.suon.co.uk/product/1/7/3/" | sed -n 's;\(http://[^/]*/\).*;\1;p'

wynik:

http://www.suon.co.uk/

8
Odnośnie ostatnich edycji: Nawiasy są rodzajem nawiasów klamrowych, więc nazywanie ich nawiasami nie jest błędem, szczególnie jeśli podąża się za słowem z rzeczywistymi znakami, tak jak zrobił to autor. Ponadto jest to preferowane użycie w niektórych kulturach, więc zastąpienie go preferowanym użyciem we własnej kulturze wydaje się nieco niegrzeczne, chociaż jestem pewien, że nie tak zamierzał redaktor. Osobiście myślę, że najlepiej użyć czysto opisowych nazw, takich jak nawiasy okrągłe , nawiasy kwadratowe i wsporników kątowych .
Alan Moore,

2
Czy można zastąpić separator łańcuchem?
Rachunek

37

sed nie obsługuje operatora „nie chciwego”.

Musisz użyć operatora „[]”, aby wykluczyć „/” z dopasowania.

sed 's,\(http://[^/]*\)/.*,\1,'

PS nie ma potrzeby wykonywania odwrotnego ukośnika „/”.


nie całkiem. jeśli separator może być jednym z wielu możliwych znaków (powiedz tylko ciąg liczb), dopasowanie negacji może być coraz bardziej złożone. to jest w porządku, ale na pewno byłoby miło mieć opcję. * non greedy
gesell

1
Pytanie było bardziej ogólne. Te rozwiązania działają w przypadku adresów URL, ale nie (np.) W moim przypadku użycia usuwania zer na końcu. s/([[:digit:]]\.[[1-9]]*)0*/\1/oczywiście nie działałby dobrze 1.20300. Ponieważ pierwotne pytanie dotyczyło adresów URL, należy je wymienić w zaakceptowanej odpowiedzi.
Daniel H

33

Symulowanie leniwego (niechcianego) kwantyfikatora w sed

I wszystkie inne smaki regex!

  1. Znajdowanie pierwszego wystąpienia wyrażenia:

    • POSIX ERE (przy użyciu -ropcji)

      Regex:

      (EXPRESSION).*|.

      Sed:

      sed -r 's/(EXPRESSION).*|./\1/g' # Global `g` modifier should be on

      Przykład (znalezienie pierwszej sekwencji cyfr) Demo na żywo :

      $ sed -r 's/([0-9]+).*|./\1/g' <<< 'foo 12 bar 34'
      12

      Jak to działa ?

      To wyrażenie regularne korzysta z alternacji |. Na każdej pozycji silnik próbuje wybrać najdłuższe dopasowanie (jest to standard POSIX, po którym następuje również kilka innych silników), co oznacza, że ​​działa tak .długo, aż zostanie znalezione dopasowanie ([0-9]+).*. Ale porządek też jest ważny.

      wprowadź opis zdjęcia tutaj

      Ponieważ ustawiono flagę globalną, silnik próbuje kontynuować dopasowywanie znak po znaku do końca ciągu wejściowego lub naszego celu. Gdy tylko pierwsza i jedyna grupa przechwytująca lewej strony naprzemiennej zostanie dopasowana, (EXPRESSION)reszta linii jest natychmiast zużywana .*. Teraz utrzymujemy naszą wartość w pierwszej grupie przechwytywania.

    • POSIX BRE

      Regex:

      \(\(\(EXPRESSION\).*\)*.\)*

      Sed:

      sed 's/\(\(\(EXPRESSION\).*\)*.\)*/\3/'

      Przykład (znalezienie pierwszej sekwencji cyfr):

      $ sed 's/\(\(\([0-9]\{1,\}\).*\)*.\)*/\3/' <<< 'foo 12 bar 34'
      12

      Ten jest jak wersja ERE, ale nie wymaga zmiany. To wszystko. Na każdej pozycji silnik próbuje dopasować cyfrę.

      wprowadź opis zdjęcia tutaj

      Jeśli zostanie znalezione, inne kolejne cyfry zostaną zużyte i przechwycone, a reszta linii zostanie dopasowana natychmiast, w przeciwnym razie *oznacza więcej lub zero , pomija drugą grupę przechwytywania \(\([0-9]\{1,\}\).*\)*i dociera do kropki .odpowiadającej jednemu znakowi, a proces ten jest kontynuowany.

  2. Znajdowanie pierwszego wystąpienia wyrażenia rozdzielanego :

    To podejście będzie pasować do pierwszego wystąpienia rozdzielanego łańcucha. Możemy to nazwać blokiem łańcucha.

    sed 's/\(END-DELIMITER-EXPRESSION\).*/\1/; \
         s/\(\(START-DELIMITER-EXPRESSION.*\)*.\)*/\1/g'

    Ciąg wejściowy:

    foobar start block #1 end barfoo start block #2 end

    -EDE: end

    -SDE: start

    $ sed 's/\(end\).*/\1/; s/\(\(start.*\)*.\)*/\1/g'

    Wynik:

    start block #1 end

    Pierwsze wyrażenie regularne \(end\).*dopasowuje i przechwytuje ogranicznik pierwszego końca endi podstawniki wszystkie pasują do ostatnio przechwyconych znaków, które są ogranicznikiem końca. Na tym etapie nasza produkcja jest: foobar start block #1 end.

    wprowadź opis zdjęcia tutaj

    Następnie wynik jest przekazywany do drugiego wyrażenia regularnego, \(\(start.*\)*.\)*który jest taki sam jak wersja POSIX BRE powyżej. Dopasowuje pojedynczy znak, jeśli ogranicznik początkowy startnie jest dopasowany, w przeciwnym razie dopasowuje i przechwytuje ogranicznik początkowy i dopasowuje pozostałe znaki.

    wprowadź opis zdjęcia tutaj


Bezpośrednio odpowiadając na twoje pytanie

Stosując podejście nr 2 (wyrażenie rozdzielane), powinieneś wybrać dwa odpowiednie wyrażenia:

  • EDE: [^:/]\/

  • SDE: http:

Stosowanie:

$ sed 's/\([^:/]\/\).*/\1/g; s/\(\(http:.*\)*.\)*/\1/' <<< 'http://www.suepearson.co.uk/product/174/71/3816/'

Wynik:

http://www.suepearson.co.uk/

Uwaga: nie będzie działać z identycznymi ogranicznikami.


3) sugerując witryny takie jak regex101 na potrzeby wersji demo, dodaj uwagę, że nie zawsze jest ono odpowiednie dla narzędzi cli ze względu na różnice w składni i
funkcjach

1
@ Sundeep Dziękujemy. Wszystkie te cytaty zamieniłem na pojedyncze. Uważałem również, że należy wspomnieć o najdłuższej z lewej reguły dopasowania. Jednak we sedwszystkich innych silnikach zgodnych z tą samą standardową kolejnością ma znaczenie, jeśli chodzi o równość. Więc echo 'foo 1' | sed -r 's/.|([0-9]+).*/\1/g'nie pasuje, ale echo 'foo 1' | sed -r 's/([0-9]+).*|./\1/g'ma.
revo

@ Sundeep również obejście dla wyrażeń rozdzielanych nie działało dla identycznych ograniczników początkowych i końcowych, dla których dodałem notatkę.
revo

świetny punkt o tym, co się dzieje, gdy różne alternacje zacząć od samej lokalizacji i mają taką samą długość, przypuszczam, że będziemy śledzić lewo-prawo porządku jak inne silniki .. trzeba spojrzeć w górę, jeśli jest to opisane w instrukcji
Sundeep

jest tu jednak dziwny przypadek: stackoverflow.com/questions/59683820/…
Niedziela

20

Nie chciwe rozwiązanie dla więcej niż jednego znaku

Ten wątek jest naprawdę stary, ale zakładam, że ludzie nadal go potrzebują. Powiedzmy, że chcesz zabić wszystko do pierwszego wystąpienia HELLO. Nie możesz powiedzieć [^HELLO]...

Dobre rozwiązanie składa się z dwóch etapów, zakładając, że możesz zaoszczędzić unikalne słowo, którego nie oczekujesz, powiedzmy top_sekrit.

W takim przypadku możemy:

s/HELLO/top_sekrit/     #will only replace the very first occurrence
s/.*top_sekrit//        #kill everything till end of the first HELLO

Oczywiście przy prostszym wprowadzeniu można użyć mniejszego słowa, a może nawet jednego znaku.

HTH!


4
Aby było jeszcze lepiej, przydatne w sytuacji, gdy nie możesz oczekiwać nieużywanego znaku: 1. zamień ten znak specjalny na naprawdę nieużywane SŁOWO, 2. zamień sekwencję końcową na znak specjalny, 3. wykonaj wyszukiwanie kończące się znakiem specjalnym, 4 , zamień z powrotem znak specjalny, 5. zamień z powrotem specjalny WORD. Na przykład, chcesz chciwego operatora między <hello> a </hello>:
Jakub

3
Oto przykład: echo "Znajdź: <hello> fir ~ st <br> tak </hello> <hello> sec ~ ond </hello>" | sed -e "s, ~, VERYSPECIAL, g" -e "s, </hello>, ~, g" -e "s,. * Znajdź: <hello> ([^ ~] *). *, \ 1 , „-e” s, \ ~, </hello>, „-e” s, VERYSPECIAL, ~, ”
Jakub

2
Zgadzam się. fajne rozwiązanie. Chciałbym przeformułować komentarz w następujący sposób: jeśli nie możesz polegać na ~ nieużywaniu, zamień jego obecne wystąpienia najpierw za pomocą s / ~ / VERYspeciaL / g, następnie wykonaj powyższą sztuczkę, a następnie zwróć oryginał ~ za pomocą s / VERYspeciaL / ~ / g
ishahak

1
Zwykle lubię używać rzadszych „zmiennych” do tego rodzaju rzeczy, więc zamiast tego `użyłbym <$$>(ponieważ $$rozwija się do twojego identyfikatora procesu w powłoce, chociaż będziesz musiał użyć podwójnych cudzysłowów zamiast pojedynczych cudzysłowów, i to może uszkodzić inne części wyrażenia regularnego) lub, jeśli dostępny jest Unicode, coś podobnego <∈∋>.
Adam Katz

W pewnym momencie musisz zadać sobie pytanie, dlaczego zamiast tego używasz perllub pythoninnego języka. perlrobi to w mniej delikatny sposób w jednym wierszu ...
ArtOfWarfare

18

sed - nie chciwe dopasowanie przez Christopha Siegharta

Sztuką, aby uzyskać nie chciwe dopasowanie w sed, jest dopasowanie wszystkich znaków oprócz tej, która kończy dopasowanie. Wiem, że to oczywiste, ale zmarnowałem na to cenne minuty, a skrypty powłoki powinny być w końcu szybkie i łatwe. Na wypadek, gdyby ktoś inny mógł go potrzebować:

Chciwe dopasowanie

% echo "<b>foo</b>bar" | sed 's/<.*>//g'
bar

Nie chciwe dopasowanie

% echo "<b>foo</b>bar" | sed 's/<[^>]*>//g'
foobar

17

Można to zrobić za pomocą cut:

echo "http://www.suepearson.co.uk/product/174/71/3816/" | cut -d'/' -f1-3

9

innym sposobem, nie używając wyrażenia regularnego, jest użycie metody pola / separator np

string="http://www.suepearson.co.uk/product/174/71/3816/"
echo $string | awk -F"/" '{print $1,$2,$3}' OFS="/"

5

sed na pewno ma swoje miejsce, ale to nie jeden z nich!

Jak zauważył Dee: po prostu użyj cut. W tym przypadku jest to znacznie prostsze i znacznie bezpieczniejsze. Oto przykład, w którym wyodrębniamy różne składniki z adresu URL przy użyciu składni Bash:

url="http://www.suepearson.co.uk/product/174/71/3816/"

protocol=$(echo "$url" | cut -d':' -f1)
host=$(echo "$url" | cut -d'/' -f3)
urlhost=$(echo "$url" | cut -d'/' -f1-3)
urlpath=$(echo "$url" | cut -d'/' -f4-)

daje Ci:

protocol = "http"
host = "www.suepearson.co.uk"
urlhost = "http://www.suepearson.co.uk"
urlpath = "product/174/71/3816/"

Jak widać, jest to bardziej elastyczne podejście.

(wszystkie podziękowania dla Dee)



3

sed -E interpretuje wyrażenia regularne jako rozszerzone (nowoczesne) wyrażenia regularne

Aktualizacja: -E na MacOS X, -r w GNU sed.


4
Nie, nie robi ... Przynajmniej nie GNU sed.
Michel de Ruiter,

7
Mówiąc szerzej, -Ejest unikalny dla BSD, seda zatem OS X. Linki do stron podręcznika man. -rwprowadza rozszerzone wyrażenia regularne do GNU,sed jak zauważono w poprawce @ stephancheg. Uważaj podczas używania polecenia o znanej zmienności w różnych dystrybucjach nix. Nauczyłem się tego na własnej skórze.
fny

1
To jest poprawna odpowiedź, jeśli chcesz użyć sed, i jest najbardziej odpowiednia do pierwszego pytania.
Czy Tice

8
-rOpcja GNU sed zmienia tylko reguły zmiany znaczenia, zgodnie Appendix A Extended regular expressionsz plikiem informacyjnym i kilkoma szybkimi testami; tak naprawdę nie dodaje niepochodnego kwalifikatora ( GNU sed version 4.2.1przynajmniej od tego.)
eichin

1
GNU sed -Eprzez pewien czas uznawana była za nieudokumentowaną opcję, ale w wersji 4.2.2.177 dokumentacja została zaktualizowana, aby to odzwierciedlić, więc teraz -Ejest w porządku dla obu.
Benjamin W.,

3

Nadal istnieje nadzieja na rozwiązanie tego problemu za pomocą czystego (GNU) sed. Mimo że nie jest to ogólne rozwiązanie, w niektórych przypadkach można użyć „pętli”, aby wyeliminować wszystkie niepotrzebne części łańcucha:

sed -r -e ":loop" -e 's|(http://.+)/.*|\1|' -e "t loop"
  • -r: Użyj rozszerzonego wyrażenia regularnego (dla nawiasu + i nieskalowanego)
  • „: loop”: zdefiniuj nową etykietę o nazwie „loop”
  • -e: dodaj polecenia do sed
  • „t loop”: w przypadku pomyślnej zamiany wróć do etykiety „loop”

Jedynym problemem jest to, że wycina również ostatni znak separatora ('/'), ale jeśli naprawdę go potrzebujesz, możesz po prostu odłożyć go z powrotem po zakończeniu pętli, po prostu dodaj to dodatkowe polecenie na końcu poprzedniego wiersz poleceń:

-e "s,$,/,"

2

Ponieważ wyraźnie stwierdziłeś, że próbujesz użyć sed (zamiast perl, cut itp.), Spróbuj pogrupować. To omija niechciany identyfikator potencjalnie nierozpoznany. Pierwszą grupą jest protokół (tj. „Http: //”, „https: //”, „tcp: //” itp.). Druga grupa to domena:

echo „http://www.suon.co.uk/product/1/7/3/” | sed "s | ^ \ (. * // \) \ ([^ /] * \). * $ | \ 1 \ 2 |"

Jeśli nie znasz grupowania, zacznij tutaj .


1

Zdaję sobie sprawę, że to stary wpis, ale ktoś może uznać go za przydatny. Ponieważ pełna nazwa domeny nie może przekraczać całkowitej długości 253 znaków, zamień. * Na. \ {1, 255 \}


1

Oto jak solidnie wykonywać niechciane dopasowanie ciągów wieloznakowych za pomocą sed. Powiedzmy, że chcemy zmienić każdy foo...barsię <foo...bar>więc na przykład tego wejścia:

$ cat file
ABC foo DEF bar GHI foo KLM bar NOP foo QRS bar TUV

powinien stać się tym wyjściem:

ABC <foo DEF bar> GHI <foo KLM bar> NOP <foo QRS bar> TUV

Aby to zrobić, przekonwertuj foo i pasek na pojedyncze znaki, a następnie użyj negacji tych znaków między nimi:

$ sed 's/@/@A/g; s/{/@B/g; s/}/@C/g; s/foo/{/g; s/bar/}/g; s/{[^{}]*}/<&>/g; s/}/bar/g; s/{/foo/g; s/@C/}/g; s/@B/{/g; s/@A/@/g' file
ABC <foo DEF bar> GHI <foo KLM bar> NOP <foo QRS bar> TUV

W powyższym:

  1. s/@/@A/g; s/{/@B/g; s/}/@C/gkonwertuje {i }na łańcuchy znaków zastępczych, które nie mogą istnieć w danych wejściowych, więc te znaki są wtedy dostępne do konwersji fooi bar.
  2. s/foo/{/g; s/bar/}/gwspółczynnik konwersji fooi bardo {i }odpowiednio
  3. s/{[^{}]*}/<&>/gwykonuje op chcemy - konwersja foo...bardo<foo...bar>
  4. s/}/bar/g; s/{/foo/gkonwertuje {i }wraca do fooibar .
  5. s/@C/}/g; s/@B/{/g; s/@A/@/g konwertuje łańcuchy znaków zastępczych z powrotem na ich oryginalne znaki.

Zauważ, że powyższe nie polega na tym, że żaden konkretny ciąg nie jest obecny na wejściu, ponieważ produkuje takie ciągi w pierwszym kroku, ani nie przejmuje się tym, które wystąpienie określonego wyrażenia regularnego chcesz dopasować, ponieważ możesz użyć {[^{}]*}tyle razy, ile to konieczne. w wyrażeniu, aby wyodrębnić właściwe dopasowanie i / lub operatorem dopasowania numerycznego seds, np. aby zastąpić tylko 2 wystąpienie:

$ sed 's/@/@A/g; s/{/@B/g; s/}/@C/g; s/foo/{/g; s/bar/}/g; s/{[^{}]*}/<&>/2; s/}/bar/g; s/{/foo/g; s/@C/}/g; s/@B/{/g; s/@A/@/g' file
ABC foo DEF bar GHI <foo KLM bar> NOP foo QRS bar TUV

1

Nie widziałem jeszcze tej odpowiedzi, więc możesz to zrobić za pomocą vilub vim:

vi -c '%s/\(http:\/\/.\{-}\/\).*/\1/ge | wq' file &>/dev/null

To powoduje vi :%sglobalne podstawienie (końcowe g), powstrzymuje się od zgłaszania błędu, jeśli wzorzec nie zostanie znaleziony ( e), a następnie zapisuje wynikowe zmiany na dysku i kończy pracę. W &>/dev/nullzapobiega GUI z krótko migać na ekranie, co może być uciążliwe.

I jak za pomocą viczasami bardzo skomplikowane regexes, ponieważ (1) Perl jest martwy umieranie, (2) Vim posiada bardzo zaawansowany silnik regex, oraz (3) Jestem już zaznajomiony z viregexes w moim edycji użytkowania z dnia na dzień dokumenty


0
echo "/home/one/two/three/myfile.txt" | sed 's|\(.*\)/.*|\1|'

nie przejmuj się, mam to na innym forum :)


4
więc masz chciwego mecz: /home/one/two/three/jeśli dodasz inny /jak /home/one/two/three/four/myfile.txtwas łapczywie dopasować fourtakże: /home/one/two/three/four, pytanie o zakaz chciwy
stefanb


0

Oto coś, co możesz zrobić, stosując dwustopniowe podejście i awk:

A=http://www.suepearson.co.uk/product/174/71/3816/  
echo $A|awk '  
{  
  var=gensub(///,"||",3,$0) ;  
  sub(/\|\|.*/,"",var);  
  print var  
}'  

Wyjście: http://www.suepearson.co.uk

Mam nadzieję, że to pomaga!


0

Kolejna wersja sed:

sed 's|/[:alnum:].*||' file.txt

Pasuje /po nim znak alfanumeryczny (więc nie kolejny ukośnik), a także reszta znaków do końca linii. Następnie zastępuje go niczym (tzn. Usuwa.)


1
Chyba powinno być "[[:alnum:]]", nie "[:alphanum:]".
oli_arborum
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.