Jaki powinien być wynik, jeśli dane wejściowe to Here is a Here String? Albo I Hereby Dub Thee Sir Stringy?
ghoti
5
FYI. Twoje polecenie oznacza wydrukowanie wszystkiego między wierszem zawierającym słowo Here a wierszem zawierającym słowo String - nie to, co chcesz.
Dzięki! A co jeśli chciałbym znaleźć wszystko pomiędzy „jeden to” a „ciągiem” w „tu jest jeden to ciąg”? (sed -e 's / one to (. *) String / \ 1 /'?
user1190650
5
@ user1190650 To zadziała, jeśli chcesz również zobaczyć „Tutaj jest”. Można przetestować go: echo "Here is a one is a String" | sed -e 's/one is\(.*\)String/\1/'. Jeśli chcesz tylko część między „jest” i „String”, to trzeba zrobić regex dopasować cały wiersz: sed -e 's/.*one is\(.*\)String.*/\1/'. W sed, s/pattern/replacement/powiedz „zastąp 'zamiennik' dla 'wzorca' w każdym wierszu”. Zmieni tylko wszystko, co pasuje do „wzorca”, więc jeśli chcesz zastąpić całą linię, musisz dopasować „wzorzec” do całej linii.
Brian Campbell
9
To się psuje, gdy wejście toHere is a String Here is a String
Jay D
1
Byłoby wspaniale zobaczyć rozwiązanie dla przypadku: „Oto bla bla Ciąg Oto 1 a bla bla Ciąg Tutaj jest 2 blash blash Ciąg” wyjście powinno pobrać tylko pierwszy podciąg między Tutaj a Ciągiem ”
Jay D
1
@JayD sed nie obsługuje niechcianych dopasowań, zobacz to pytanie, aby poznać zalecane alternatywy.
Brian Campbell
180
GNU grep może również obsługiwać pozytywne i negatywne przewidywanie i cofanie: w twoim przypadku polecenie wyglądałoby tak:
echo "Here is a string"| grep -o -P '(?<=Here).*(?=string)'
$ echo 'Here is a string, and Here is another string.'| grep -oP '(?<=Here).*(?=string)'# Greedy match
is a string, and Here is another
$ echo 'Here is a string, and Here is another string.'| grep -oP '(?<=Here).*?(?=string)'# Non-greedy match (Notice the '?' after '*' in .*)
is a
is another
Zauważ, że -Popcja GNU grep nie istnieje w grepdołączonym do * BSD, ani w tych, które są dostarczane z jakimkolwiek SVR4 (Solaris itp.). We FreeBSD można zainstalować devel/pcreport, który zawiera pcregrep, który obsługuje PCRE (i antycypację / wstecz). Starsze wersje OSX wykorzystywały GNU grep, ale w OSX Mavericks -Pwywodzi się z wersji FreeBSD, która nie zawiera tej opcji.
ghoti
1
Cześć, jak wyodrębnić tylko odrębną zawartość?
Durgesh Suthar,
4
To nie działa, ponieważ jeśli końcowy ciąg znaków „łańcuch” występuje więcej niż raz, otrzyma ostatnie wystąpienie, a nie następne wystąpienie.
Buttle Butkus
6
W przypadku Here is a string a string, oba" is a " i " is a string a "są poprawnymi odpowiedziami (zignoruj cudzysłowy), zgodnie z wymaganiami pytania. To zależy od Ciebie, które jeden z nich ty chcesz, a następnie odpowiedź może być inna odpowiednio. W każdym razie, według twojego wymagania, to zadziała:echo "Here is a string a string" | grep -o -P '(?<=Here).*?(?=string)'
Twoja odpowiedź jest obiecująca. Jednak jeden problem. Jak mogę wyodrębnić go do pierwszego widocznego ciągu, jeśli w tym samym wierszu znajduje się wiele ciągów? Dzięki
Mian Asbat Ahmad
@MianAsbatAhmad Chciałbyś, aby *kwantyfikator między Herei był niechciwy String(lub leniwy). Jednak typ wyrażenia regularnego używany przez sed nie obsługuje leniwych kwantyfikatorów (a ?bezpośrednio po .*) zgodnie z tym pytaniem Stackoverflow. Zwykle, aby zaimplementować leniwy kwantyfikator, po prostu dopasujesz wszystko z wyjątkiem tokena, którego nie chcesz dopasować, ale w tym przypadku nie ma tylko jednego tokenu, zamiast tego jest to cały ciąg String.
dlaczego ta metoda jest tak powolna? podczas usuwania dużej strony html tą metodą trwa to około 10 sekund.
Adam Johns
@AdamJohns, która metoda? PCRE jeden? Analiza PCRE jest dość skomplikowana, ale 10 sekund wydaje się ekstremalne. Jeśli jesteś zaniepokojony, radzę zadać pytanie z przykładowym kodem i zobaczyć, co mówią eksperci.
ghoti
Myślę, że było to dla mnie tak powolne, ponieważ zawierało bardzo duże źródło pliku html w zmiennej. Kiedy zapisałem zawartość do pliku, a następnie przeanalizowałem plik, prędkość dramatycznie wzrosła.
Adam Johns
22
Dzięki GNU awk
$ echo "Here is a string"| awk -v FS="(Here|string)"'{print $2}'
is a
grep z obsługą parametrów -P( perl-regexp ) \K, co pomaga w odrzucaniu wcześniej dopasowanych znaków. W naszym przypadku poprzednio dopasowanym ciągiem byłHere usunięty z końcowego wyniku.
$ echo "Here is a string"| grep -oP 'Here\K.*(?=string)'
is a
$ echo "Here is a string"| grep -oP 'Here\K(?:(?!string).)*'
is a
Jeśli chcesz, aby wynik był, is amożesz wypróbować poniższe,
$ echo "Here is a string"| grep -oP 'Here\s*\K.*(?=\s+string)'
is a
$ echo "Here is a string"| grep -oP 'Here\s*\K(?:(?!\s+string).)*'
is a
To nie działa dla :, echo "Here is a string dfdsf Here is a string" | awk -v FS="(Here|string)" '{print $2}'zwraca tylko is azamiast powinno być is a is a@Avinash Raj
alper
20
Jeśli masz długi plik z wieloma wystąpieniami w wielu wierszach, warto najpierw wydrukować wiersze liczbowe:
Dzięki! To jedyne rozwiązanie, które zadziałało w moim przypadku (plik tekstowy z wieloma wierszami, a nie pojedynczy ciąg bez znaków końca wiersza). Oczywiście, aby mieć to bez numeracji linii, należy pominąć -nopcję in cat.
Jeffrey Lebowski
... w takim przypadku catmożna całkowicie pominąć; sedwie, jak czytać plik lub standardowe wejście.
tripleee
9
To może zadziałać dla Ciebie (GNU sed):
sed '/Here/!d;s//&\n/;s/.*\n//;:a;/String/bb;$!{n;ba};:b;s//\n&/;P;D' file
Przedstawia każdą reprezentację tekstu między dwoma znacznikami (w tym przypadku Herei String) w nowej linii i zachowuje nowe linie w tekście.
Wszystkie powyższe rozwiązania mają wady, w których ostatni ciąg wyszukiwania jest powtarzany w innym miejscu ciągu. Uważam, że najlepiej jest napisać funkcję bash.
function str_str {local str
str="${1#*${2}}"
str="${str%%$3*}"
echo -n "$str"}# test it ...
mystr="this is a string"
str_str "$mystr""this "" string"
$ echo "Here is a String"| sed 's/.*Here//; s/String.*//'
is a
Działa również
$ echo "Here is a StringHere is a String"| sed 's/.*Here//; s/String.*//'
is a
$ echo "Here is a StringHere is a StringHere is a StringHere is a String"| sed 's/.*Here//; s/String.*//'
is a
To usuwa ciągi zamiast wyprowadzać coś pomiędzy. Spróbuj usunąć „Hello” z „is” w poleceniu sed, a wyświetli się „Hello a”
Jonathan
1
Problem. Moje zapisane wiadomości Claws Mail są opakowane w następujący sposób, a ja próbuję wyodrębnić wiersze tematu:
Subject:[SLC38A9 lysosomal arginine sensor; mTORC1 pathway]Key molecular
link in major cell growth pathway:Findings point to new potential
therapeutic target in pancreatic cancer [mTORC1 Activator SLC38A9 IsRequired to EffluxEssentialAminoAcids from Lysosomes and UseProtein as
a Nutrient][Re:Nutrient sensor in key growth-regulating metabolic pathway
identified [Lysosomal amino acid transporter SLC38A9 signals arginine
sufficiency to mTORC1]]Message-ID:<20171019190902.18741771@VictoriasJourney.com>
[SLC38A9 lysosomal arginine sensor; mTORC1 pathway]Key molecular link in major cell growth pathway:Findings point to new potential therapeutic target in pancreatic cancer [mTORC1 Activator SLC38A9 IsRequired to EffluxEssentialAminoAcids from Lysosomes and UseProtein as a Nutrient][Re:Nutrient sensor in key growth-regulating metabolic pathway identified [Lysosomal amino acid transporter SLC38A9 signals arginine sufficiency to mTORC1]]
sed ':a;N;$!ba;s/\n/ /g' corpus/01| grep -o -P '(?<=Subject: ).*(?=Message-ID:)'
co daje
[SLC38A9 lysosomal arginine sensor; mTORC1 pathway]Key molecular link in major cell growth pathway:Findings point to new potential therapeutic target in pancreatic cancer [mTORC1 Activator SLC38A9 IsRequired to EffluxEssentialAminoAcids from Lysosomes and UseProtein as a Nutrient][Re:Nutrient sensor in key growth-regulating metabolic pathway identified [Lysosomal amino acid transporter SLC38A9 signals arginine sufficiency to mTORC1]]
[SLC38A9 lysosomal arginine sensor; mTORC1 pathway]Key molecular link in major cell growth pathway:Findings point to new potential therapeutic target in pancreatic cancer [mTORC1 Activator SLC38A9 IsRequired to EffluxEssentialAminoAcids from Lysosomes and UseProtein as a Nutrient][Re:Nutrient sensor in key growth-regulating metabolic pathway identified [Lysosomal amino acid transporter SLC38A9 signals arginine sufficiency to mTORC1]]
Here is a Here String
? AlboI Hereby Dub Thee Sir Stringy
?sed
zadawane pytania to „jak wyodrębnić tekst między poszczególnymi wierszami”; to jest stackoverflow.com/questions/16643288/ ...Odpowiedzi:
źródło
echo "Here is a one is a String" | sed -e 's/one is\(.*\)String/\1/'
. Jeśli chcesz tylko część między „jest” i „String”, to trzeba zrobić regex dopasować cały wiersz:sed -e 's/.*one is\(.*\)String.*/\1/'
. W sed,s/pattern/replacement/
powiedz „zastąp 'zamiennik' dla 'wzorca' w każdym wierszu”. Zmieni tylko wszystko, co pasuje do „wzorca”, więc jeśli chcesz zastąpić całą linię, musisz dopasować „wzorzec” do całej linii.Here is a String Here is a String
GNU grep może również obsługiwać pozytywne i negatywne przewidywanie i cofanie: w twoim przypadku polecenie wyglądałoby tak:
Jeśli występuje wiele wystąpień
Here
istring
, możesz wybrać, czy chcesz dopasować od pierwszegoHere
do ostatniego,string
czy też dopasować je indywidualnie. W przypadku wyrażenia regularnego nazywa się to dopasowaniem zachłannym (pierwszy przypadek) lub niechcianym dopasowaniem (drugi przypadek)źródło
-P
opcja GNU grep nie istnieje wgrep
dołączonym do * BSD, ani w tych, które są dostarczane z jakimkolwiek SVR4 (Solaris itp.). We FreeBSD można zainstalowaćdevel/pcre
port, który zawierapcregrep
, który obsługuje PCRE (i antycypację / wstecz). Starsze wersje OSX wykorzystywały GNU grep, ale w OSX Mavericks-P
wywodzi się z wersji FreeBSD, która nie zawiera tej opcji.Here is a string a string
, oba" is a "
i" is a string a "
są poprawnymi odpowiedziami (zignoruj cudzysłowy), zgodnie z wymaganiami pytania. To zależy od Ciebie, które jeden z nich ty chcesz, a następnie odpowiedź może być inna odpowiednio. W każdym razie, według twojego wymagania, to zadziała:echo "Here is a string a string" | grep -o -P '(?<=Here).*?(?=string)'
echo $'Here is \na string' | grep -zoP '(?<=Here)(?s).*(?=string)'
Zaakceptowana odpowiedź nie usuwa tekstu, który może znajdować się przed
Here
lub poString
. To będzie:Główną różnicą jest dodanie
.*
bezpośrednio przedHere
i poString
.źródło
*
kwantyfikator międzyHere
i był niechciwyString
(lub leniwy). Jednak typ wyrażenia regularnego używany przez sed nie obsługuje leniwych kwantyfikatorów (a?
bezpośrednio po.*
) zgodnie z tym pytaniem Stackoverflow. Zwykle, aby zaimplementować leniwy kwantyfikator, po prostu dopasujesz wszystko z wyjątkiem tokena, którego nie chcesz dopasować, ale w tym przypadku nie ma tylko jednego tokenu, zamiast tego jest to cały ciągString
..
nie odpowiada podziałom linii. Jeśli chcesz dopasować podziały linii, możesz zastąpić.
coś w rodzaju[\s\s]
.Możesz usunąć struny w samym Bash :
A jeśli masz GNU grep, które zawiera PCRE , możesz użyć asercji o zerowej szerokości:
źródło
Dzięki GNU awk
grep z obsługą parametrów
-P
( perl-regexp )\K
, co pomaga w odrzucaniu wcześniej dopasowanych znaków. W naszym przypadku poprzednio dopasowanym ciągiem byłHere
usunięty z końcowego wyniku.Jeśli chcesz, aby wynik był,
is a
możesz wypróbować poniższe,źródło
echo "Here is a string dfdsf Here is a string" | awk -v FS="(Here|string)" '{print $2}'
zwraca tylkois a
zamiast powinno byćis a is a
@Avinash RajJeśli masz długi plik z wieloma wystąpieniami w wielu wierszach, warto najpierw wydrukować wiersze liczbowe:
źródło
-n
opcję incat
.cat
można całkowicie pominąć;sed
wie, jak czytać plik lub standardowe wejście.To może zadziałać dla Ciebie (GNU sed):
Przedstawia każdą reprezentację tekstu między dwoma znacznikami (w tym przypadku
Here
iString
) w nowej linii i zachowuje nowe linie w tekście.źródło
Wszystkie powyższe rozwiązania mają wady, w których ostatni ciąg wyszukiwania jest powtarzany w innym miejscu ciągu. Uważam, że najlepiej jest napisać funkcję bash.
źródło
Możesz użyć dwóch poleceń s
Działa również
źródło
Aby zrozumieć
sed
polecenie, musimy je budować krok po kroku.Oto Twój oryginalny tekst
Spróbujmy usunąć
Here
string zs
opcją ubstition wsed
W tym momencie, wierzę, będzie można usunąć
String
równieżAle to nie jest twój pożądany wynik.
Aby połączyć dwa polecenia seda, użyj
-e
opcjiMam nadzieję że to pomoże
źródło
Możesz użyć
\1
(patrz http://www.grymoire.com/Unix/Sed.html#uh-4 ):Treść znajdująca się w nawiasach zostanie zapisana jako
\1
.źródło
Problem. Moje zapisane wiadomości Claws Mail są opakowane w następujący sposób, a ja próbuję wyodrębnić wiersze tematu:
Według A2 w tym wątku, jak używać sed / grep do wyodrębniania tekstu między dwoma słowami? pierwsze wyrażenie poniżej „działa”, o ile dopasowany tekst nie zawiera nowej linii:
Jednak pomimo wypróbowania wielu wariantów (
.+?; /s; ...
), nie mogłem sprawić, aby te działały:Rozwiązanie 1.
Za tekst Wyciąg pomiędzy dwoma łańcuchami na różnych liniach
co daje
Rozwiązanie 2. *
Per Jak mogę zamienić znak nowej linii (\ n) używając seda?
zastąpi znaki nowej linii spacją.
Łączenie tego z A2 w Jak używać sed / grep do wyodrębniania tekstu między dwoma słowami? otrzymujemy:
co daje
Ten wariant usuwa podwójne spacje:
dający
źródło