Eu tenho uma string no Bash:
string="My string"
Como posso testar se ele contém outra string?
if [ $string ?? 'foo' ]; then
echo "It's there!"
fi
Onde ??
está meu operador desconhecido. Eu uso eco e grep
?
if echo "$string" | grep 'foo'; then
echo "It's there!"
fi
Isso parece um pouco desajeitado.
expr
comando aquiRespostas:
Você também pode usar a resposta de Marcus (* curingas) fora de uma declaração de caso, se usar colchetes duplos:
Observe que os espaços na corda da agulha precisam ser colocados entre aspas duplas, e os
*
curingas devem estar do lado de fora. Observe também que um operador de comparação simples é usado (ou seja==
), não o operador regex=~
.fonte
#!/bin/sh
. Tente em#!/bin/bash
vez disso.[[
. Veja como ideone.com/ZSy1gZSe você preferir a abordagem regex:
fonte
=~
operador já pesquisa uma sequência inteira para uma correspondência; os.*
aqui são estranhos. Além disso, as citações são geralmente preferível barras invertidas:[[ $string =~ "My s" ]]
E14)
. Provavelmente, é melhor atribuir a uma variável (usando aspas) e comparar. Assim:re="My s"; if [[ $string =~ $re ]]
if [[ ! "abc" =~ "d" ]]
é verdadeira.number=2; if [[ "1, 2, 4, 5" = *${number}* ]]; then echo forward $number; fi; if [[ *${number}* = "1, 2, 4, 5" ]]; then echo backwards $number; fi;
Não tenho certeza sobre o uso de uma instrução if, mas você pode obter um efeito semelhante com uma instrução case:
fonte
[[ $string == *foo* ]]
também funciona em algumas versões sh compatível com POSIX (por exemplo,/usr/xpg4/bin/sh
no Solaris 10) e ksh (> = 88)[[
... o comutador de caixa funcionou!stringContain
variantes (compatível ou independente de maiúsculas e minúsculas)Como essas respostas do Stack Overflow falam principalmente sobre o Bash , publiquei uma função Bash independente do caso na parte inferior deste post ...
De qualquer forma, existe o meu
Resposta compatível
Como já existem muitas respostas usando os recursos específicos do Bash, existe uma maneira de trabalhar com shells com recursos mais ruins , como o BusyBox :
Na prática, isso poderia dar:
Isso foi testado em Bash, Dash , KornShell (
ksh
) e ash (BusyBox), e o resultado é sempre:Em uma função
Conforme solicitado por @EeroAaltonen, aqui está uma versão da mesma demonstração, testada sob as mesmas conchas:
Então:
Aviso: você precisa escapar ou colocar aspas duplas e / ou aspas duplas:
Função simples
Isso foi testado no BusyBox, Dash e, é claro, no Bash:
Então agora:
... Ou se a string enviada pudesse estar vazia, como apontado por @Sjlver, a função se tornaria:
ou conforme sugerido pelo comentário de Adrian Günter , evitando
-o
interrupções:Função final (simples):
E invertendo os testes para torná-los potencialmente mais rápidos:
Com cadeias vazias:
Independente de maiúsculas e minúsculas (somente Bash!)
Para testar seqüências de caracteres sem o cuidado de maiúsculas e minúsculas, basta converter cada sequência em minúsculas:
Verifica:
fonte
string_contains() { [ -z "${2##*$1*}" ] && [ -n "$2" -o -z "$1" ]; }
um pensamento final: a string vazia contém a string vazia? A versão acima das coisas sim (por causa da-o -z "$1"
parte).Você deve se lembrar que o script de shell é menos uma linguagem e mais uma coleção de comandos. Instintivamente, você acha que esse "idioma" exige que você siga um
if
com um[
ou um[[
. Ambos são apenas comandos que retornam um status de saída indicando sucesso ou falha (como todos os outros comandos). Por esse motivo, eu usariagrep
, e não o[
comando.Apenas faça:
Agora que você está pensando
if
em testar o status de saída do comando a seguir (completo com ponto e vírgula), por que não reconsiderar a origem da string que está testando?A
-q
opção faz com que o grep não produza nada, pois queremos apenas o código de retorno.<<<
faz com que o shell expanda a próxima palavra e use-a como entrada para o comando, uma versão em uma linha do<<
documento aqui (não tenho certeza se isso é padrão ou um bashismo).fonte
if grep -q foo <(echo somefoothing); then
echo
é portável, se você estiver passando uma variável, useprintf '%s' "$string
.grep -q foo <<<"$mystring"
implie 1 garfo e é Bashismo eecho $mystring | grep -q foo
implie 2 garfos (um para o tubo e o segundo para executar/path/to/grep
)echo
sem sinalizadores ainda pode ter problemas inesperados de portabilidade se a sequência de argumentos contiver sequências de barra invertida.echo "nope\c"
é esperado em algumas plataformas para funcionar comoecho -e "nope"
em outras.printf '%s' "nope"
vsprintf '%s\n' 'nope\c'
A resposta aceita é a melhor, mas como há mais de uma maneira de fazê-lo, aqui está outra solução:
${var/search/replace}
é$var
com a primeira instância desearch
substituído porreplace
, se for encontrado (não muda$var
). Se você tentar substituirfoo
por nada, e a cadeia de caracteres mudou, então obviamentefoo
foi encontrado.fonte
Portanto, existem muitas soluções úteis para a pergunta - mas qual é mais rápida / utiliza o menor número de recursos?
Testes repetidos usando esse quadro:
Substituindo TEST toda vez:
(doContain estava na resposta de F. Houri)
E para rir:
Portanto, a opção de substituição simples vence previsivelmente, seja em um teste prolongado ou em um caso. O estojo é portátil.
A canalização para 100000 greps é previsivelmente dolorosa! A regra antiga sobre o uso de utilitários externos sem necessidade é verdadeira.
fonte
[[ $b == *$a* ]]
.case
ganha com o menor consumo de tempo geral. Você está perdendo um asterisco depois$b in *$a
. Eu obtenho resultados um pouco mais rápidos do[[ $b == *$a* ]]
quecase
com o bug corrigido, mas também pode depender de outros fatores, é claro.[[ $b == *$a* ]]
é rápido ecase
é quase tão rápido (e agradavelmente compatível com POSIX).Isso também funciona:
E o teste negativo é:
Suponho que esse estilo seja um pouco mais clássico - menos dependente dos recursos do shell Bash.
O
--
argumento é pura paranóia POSIX, usada para proteger contra seqüências de entrada semelhantes a opções, como--abc
ou-a
.Nota: Em um loop restrito, esse código será muito mais lento do que usar os recursos internos do shell Bash, pois um (ou dois) processos separados serão criados e conectados por meio de pipes.
fonte
echo
não é portável, você deve estar usandoprintf '%s' "$haystack
.echo
completamente qualquer coisa, exceto texto literal, sem escapes que não iniciem com a-
. Pode funcionar para você, mas não é portátil. Até o bashecho
se comportará de maneira diferente, dependendo de axpg_echo
opção estar definida. PS: Esqueci de fechar as aspas duplas no meu comentário anterior.--
não está listado na especificação POSIX paraprintf
, mas você deve usarprintf '%s' "$anything"
assim mesmo, para evitar problemas se$anything
contiver um%
caractere.Bash 4+ exemplos. Nota: não usar aspas causará problemas quando as palavras contiverem espaços, etc. Sempre cite no Bash, IMO.
Aqui estão alguns exemplos do Bash 4+:
Exemplo 1, verifique 'yes' na string (não faz distinção entre maiúsculas e minúsculas):
Exemplo 2, verifique 'yes' na string (não faz distinção entre maiúsculas e minúsculas):
Exemplo 3, verifique se 'yes' na string (diferencia maiúsculas de minúsculas):
Exemplo 4, verifique se 'yes' na string (diferencia maiúsculas de minúsculas):
Exemplo 5, correspondência exata (diferencia maiúsculas de minúsculas):
Exemplo 6, correspondência exata (sem distinção entre maiúsculas e minúsculas):
Exemplo 7, correspondência exata:
Exemplo 8, correspondência de curinga .ext (sem distinção entre maiúsculas e minúsculas):
Aproveitar.
fonte
Que tal agora:
fonte
Como Paulo mencionou em sua comparação de desempenho:
Isso é compatível com POSIX, como o 'case "$ string" na resposta fornecida por Marcus , mas é um pouco mais fácil de ler do que a resposta da instrução de caso. Observe também que isso será muito mais lento do que usar uma declaração de caso. Como Paulo apontou, não o use em loop.
fonte
Essa resposta de estouro de pilha foi a única a capturar espaço e trace caracteres:
fonte
fonte
echo "Couldn't find
instrução no final é um bom truque para retornar 0 status de saída para esses comandos correspondentes.|| echo "Couldn't find"
, retornará um status de saída de erro se não houver correspondência, o que talvez você não queira se estiver executando um pipeline de IC, por exemplo, onde deseja que todos os comandos retornem status de saída sem erroUm é:
fonte
expr
é um daqueles utilitários de canivete suíço que geralmente pode fazer o que você precisa fazer, depois de descobrir como fazê-lo, mas uma vez implementado, você nunca consegue se lembrar por que ou como está fazendo o que está fazendo, então você nunca toque novamente e espere que nunca pare de fazer o que está fazendo.expr
, em raras ocasiões, quando a portabilidade impede o uso do bash (por exemplo, comportamento inconsistente em versões mais antigas), tr (inconsistente em todos os lugares) ou sed (às vezes muito lento). Mas por experiência pessoal, sempre que reler essesexpr
isismos, tenho que voltar à página de manual. Então, gostaria apenas de comentar que todo uso deexpr
ser comentado ...expr
etest
foram implementadas para executá-los. Hoje em dia, geralmente existem ferramentas melhores, muitas delas embutidas em qualquer shell moderno. Acho quetest
ainda está lá, mas parece que ninguém está faltandoexpr
.Eu gosto de sed.
Editar, Lógica:
Use sed para remover a instância da substring da string
Se a nova string for diferente da antiga, existe substring
fonte
grep -q
é útil para esse fim.O mesmo usando
awk
:Resultado:
Resultado:
Fonte original: http://unstableme.blogspot.com/2008/06/bash-search-letter-in-string-awk.html
fonte
echo
não é portável, você deve estar usandoprintf '%s' "$string"
. Estou editando a resposta porque o usuário não parece mais existir.echo
não é portátil, @ nyuszika7h?Descobri que precisava dessa funcionalidade com bastante frequência, por isso estou usando uma função de shell caseira da
.bashrc
mesma maneira que permite reutilizá-la quantas vezes for necessário, com um nome fácil de lembrar:Para testar se
$string1
(digamos, abc ) está contido em$string2
(digamos, 123abcABC ), só preciso executarstringinstring "$string1" "$string2"
e verificar o valor de retorno, por exemplofonte
x
hack é necessário apenas para conchas muito antigas.Meu arquivo .bash_profile e como usei o grep:
Se a variável de ambiente PATH incluir meus dois
bin
diretórios, não os anexe.fonte
grep -q -E 'pattern1|...|patternN'
.Extensão da pergunta respondida aqui Como saber se uma string contém outra string no POSIX sh? :
Esta solução funciona com caracteres especiais:
fonte
contains "-n" "n"
não funciona aqui, porqueecho -n
engolirá o-n
como uma opção! Uma correção popular para isso é usar em seuprintf "%s\n" "$string"
lugar.Como a pergunta POSIX / BusyBox é encerrada sem fornecer a resposta correta (IMHO), vou postar uma resposta aqui.
A resposta mais curta possível é:
ou
Observe que o hash duplo é obrigatório com algumas conchas (
ash
). Acima avaliará[ stringvalue ]
quando a substring não for encontrada. Não retorna erro. Quando a substring é encontrada, o resultado está vazio e é avaliado[ ]
. Isso lançará o código de erro 1, pois a string é completamente substituída (devido a*
).A sintaxe mais curta e comum:
ou
Outro:
ou
Observe o único sinal de igual!
fonte
Correspondência exata de palavras:
fonte
Tente oobash.
É uma biblioteca de cadeias no estilo OO para o Bash 4. Possui suporte para tremas alemães. Está escrito em Bash.
Muitas funções estão disponíveis:
-base64Decode
,-base64Encode
,-capitalize
,-center
,-charAt
,-concat
,-contains
,-count
,-endsWith
,-equals
,-equalsIgnoreCase
,-reverse
,-hashCode
,-indexOf
,-isAlnum
,-isAlpha
,-isAscii
,-isDigit
,-isEmpty
,-isHexDigit
,-isLowerCase
,-isSpace
,-isPrintable
,-isUpperCase
,-isVisible
,-lastIndexOf
,-length
,-matches
,-replaceAll
,-replaceFirst
,-startsWith
,-substring
,-swapCase
,-toLowerCase
,-toString
,-toUpperCase
,-trim
, e-zfill
.Veja o exemplo contém :
oobash está disponível no Sourceforge.net .
fonte
Eu uso essa função (uma dependência não incluída, mas óbvia). Passa nos testes mostrados abaixo. Se a função retornar um valor> 0, a sequência foi encontrada. Você poderia facilmente retornar 1 ou 0.
fonte
Esta é a mesma resposta que https://stackoverflow.com/a/229585/11267590 . Mas estilo simples e também compatível com POSIX.
fonte
Isso encontrará qualquer ocorrência de a ou b ou c
fonte
O exemplo genérico do palheiro de agulhas está seguindo com variáveis
fonte