Trova la stringa conoscendone una parte e restituisci la stringa


9

Ho una stringa, per esempio

"Icecream123 AirplaneBCD CompanyTL1 ComputerYU1"

Diciamo che so che la mia stringa conterrà sicuramente la sottostringa IceCream ma non so cosa la segua.

Potrebbe essere 123 come nel mio esempio o potrebbe essere qualcosa di diverso.

Mentre posso usare grep per rilevare se la sottostringa "Icecream" esiste nella mia stringa con il seguente comando

echo $string | grep -oF 'Icecream';

Che stamperà

Icecream

Voglio un comando per farlo stampare l'intera sottostringa, che nel mio esempio è

Icecream123

Naturalmente ciò che segue Gelato è casuale e non è noto in anticipo, quindi non posso semplicemente farlo

$SUBSTRING=$(echo $string | grep -oF 'Icecream')
$SUBSTRINGTRAIL=123
echo $SUBSTRING$SUBSTRINGTRAIL

la sottostringa è fissa / statica - sempre "Icecream" o è variabile?
Jeff Schaller

uno spazio indicherà la fine del suffisso desiderato?
Jeff Schaller

@JeffSchaller Purtroppo, non lo so. In realtà sto ottenendo un output multilinea da un altro comando, che memorizzo in una variabile, questa variabile è la mia stringa $, quando viene echo visualizza l'output multilinea come una linea signle con uno spazio tra loro. In realtà non so se quello sia uno spazio o un personaggio speciale come LF. Ho pensato che fosse spazio.
Sonamor,

Voglio dire, ad esempio, Icecream123 AirplaneBCDvuoi fermarti a 123. È perché c'è uno spazio dopo il 3 o qualcos'altro?
Jeff Schaller

1
Se non sei sicuro di quali siano i tuoi dati, è difficile scrivere una soluzione appropriata. Tutte le risposte finora presumono che i tuoi dati siano su una riga, come hai mostrato. Stavo cercando di capire quale fosse il tuo delimitatore: dove si sarebbe fermata la parte "finale".
Jeff Schaller

Risposte:


15

Se il tuo grepsupporto perl espressioni regolari compatibili, potresti abbinare non avidamente fino al limite della parola successiva:

echo "$string" | grep -oP 'Icecream.*?\b'

Altrimenti, abbina la sequenza più lunga di caratteri non vuoti:

echo "$string" | grep -o 'Icecream[^[:blank:]]*'

Oppure mantieni tutto nella shell e rimuovi la sequenza di caratteri finale più lunga che inizia con uno spazio:

echo "${string%% *}"

2
Per il PCRE, userei 'Icecream\S+'per alcuni personaggi non vuoti.
Glenn Jackman,

Grazie per i tuoi commenti, purtroppo sembra che la mia versione di grep non supporti perl regex. Potresti aggiungere qualche dettaglio in più sulla tua terza opzione? Non sono sicuro di come implementarlo.
Sonamor,

Dopo alcuni altri test sembra che usando echo "$ string" | grep -oP 'Gelato. *? \ b' o 'Gelato \ S +' fa il lavoro. Grazie
Sonamor,

è davvero confuso il fatto che sebbene la variabile $ string sia una stringa, è comunque necessario inserirla tra virgolette doppie!
Sonamor,

@Sonamor in questo caso la quotazione non è strettamente necessaria; tuttavia ci sono così tanti casi in cui è una buona abitudine entrare. Vedi ad esempio quando è necessaria la doppia citazione?
steeldriver,

7

Usando un grepche sa di -o:

$ printf '%s\n' "$string" | grep -o '\<Icecream[^[:blank:]]*'
Icecream123

Il modello \<Icecream[^[:blank:]]*corrisponde alla stringa Icecream(in cui la Iè preceduta da un carattere non di parole o l'inizio della riga) seguita da zero o più spazi non vuoti (non spazi o tabulazioni).


Utilizzando awk:

$ printf '%s\n' "$string" | awk -v RS=' ' '/^Icecream/'       
Icecream123

Il awkprogramma divide la stringa in record separati da spazio e verifica ciascuno di essi. Stampa quelli che iniziano con la stringa Icecream.

Usando mawko GNU awk, puoi anche usare

printf '%s\n' "$string" | awk -v RS='[[:blank:]]' '/^Icecream/'

poiché si intersecano RScome un'espressione regolare se contiene più di un carattere.


Con sed, in modo simile come con grep:

$ printf '%s\n' "$string" | sed 's/.*\(\<Icecream[^[:blank:]]*\).*/\1/'
Icecream123

Utilizzando /bin/sh:

set -- Icecream123 AirplaneBCD CompanyTL1 ComputerYU1
for string; do
    case $string in
        Icecream*)
            printf '%s\n' "$string"
            break
    esac
done

Perl (con un piccolo aiuto da tr):

$ printf '%s\n' "$string" | tr ' ' '\n' | perl -ne '/Icecream\S*/ && print'
Icecream123

o solo

$ printf '%s\n' "$string" | perl -ne '/(Icecream\S*)/ && print $1, "\n"'
Icecream123

Oppure, dividi in righe e abbina la chiave:echo "$string" | grep -o '\S\+' | grep "Icecream"
Isaac l'

7

Dato che hai taggato bash:

[[ $string =~ (Icecream[^ ]*) ]] && result=${BASH_REMATCH[1]}

Più in generale, per un termine di ricerca in $search:

[[ $string =~ ($search[^ ]*) ]] && result=${BASH_REMATCH[1]}

... o con espansione dei parametri:

# remove any leading text up to -and through- the search text:
x=${string##*$search}

# remove any trailing space onwards
result=$search${x%% *}

2

Ad esempio, se si utilizza GNU grep:

$ echo "Icecream123 AirplaneBCD CompanyTL1 ComputerYU1" | grep -oP '\bIcecream.*?(\s|$)' --color

Utilizza PCRE.


1

Forse un po 'più semplice, soprattutto perché dici che la tua versione di grep non supporta perl regex:

$ echo $string | tr ' ' '\n' | grep 'Icecream' Icecream123

Il trdivide la stringa in linee sostituendo tutti gli spazi con nuove righe. Quindi puoi usarlo grepfacilmente.

Puoi anche scrivere quanto segue per ottenere solo ciò che segue la parola che stai cercando:

$ echo $string | tr ' ' '\n' | sed -n 's/Icecream//p' 123

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.