Encontre string enquanto conhece parte dela e retorna string

7

Eu sou novo em linux e bash, então fique comigo.

Eu tenho uma string, por exemplo

"Icecream123 AirplaneBCD CompanyTL1 ComputerYU1"

Digamos que eu saiba que minha string conterá com certeza a substring IceCream, mas não sei o que a segue.

Pode ser 123 como no meu exemplo ou pode ser algo diferente.

Enquanto eu posso usar o grep para detectar se a substring "Icecream" existe na minha string com o seguinte comando

echo $string | grep -oF 'Icecream';

Qual imprimirá

Icecream

Eu quero com um comando para conseguir imprimir toda a substring, que no meu exemplo é

Icecream123

É claro, o que segue é que o sorvete é aleatório e não é conhecido de antemão, então eu não posso simplesmente fazer

$SUBSTRING=$(echo $string | grep -oF 'Icecream')
$SUBSTRINGTRAIL=123
echo $SUBSTRING$SUBSTRINGTRAIL
    
por Sonamor 08.06.2018 / 22:02

5 respostas

13

Se o seu grep suportar expressões regulares compatíveis com o perl, você poderá corresponder de forma não avarenta até o próximo limite de palavras:

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

Caso contrário, corresponda à sequência mais longa de caracteres que não estão em branco:

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

Ou mantenha tudo no shell e remova a seqüência mais longa de caracteres iniciais começando com um espaço:

echo "${string%% *}"
    
por 08.06.2018 / 22:12
7

Usando um grep que sabe sobre -o :

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

O padrão \<Icecream[^[:blank:]]* corresponde à string Icecream (onde o I é precedido por um caractere não pertencente à palavra, ou o início da linha) seguido por zero ou mais não-brancos (não espaços ou tabulações) .

Usando awk :

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

O programa awk divide a sequência em registros separados por espaço e testa cada um deles. Ele imprimirá os que começarem com a string Icecream .

Usando mawk ou GNU awk , você também pode usar

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

pois eles interpõem RS como uma expressão regular se contiver mais de um caractere.

Com sed , de maneira semelhante a grep :

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

Usando /bin/sh :

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

Perl (com uma pequena ajuda de tr ):

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

ou apenas

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

Desde que você marcou o bash:

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

Mais geralmente, para um termo de pesquisa em $search :

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

... ou com expansão de parâmetros:

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

# remove any trailing space onwards
result=$search${x%% *}
    
por 08.06.2018 / 22:28
2

Por exemplo, se você usar GNU grep :

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

Ele usa PCRE .

    
por 08.06.2018 / 22:13
1

Um pouco mais simples, talvez, especialmente porque você diz que sua versão do grep não suporta regex perl:

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

O tr divide a string em linhas, substituindo todos os espaços por novas linhas. Então você pode usar grep facilmente.

Você também pode escrever o seguinte para obter apenas o que segue a palavra que está procurando:

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

    
por 09.06.2018 / 23:33