Gostaria de verificar se uma string começa com "node", por exemplo, "node001". Algo como
if [ $HOST == user* ]
then
echo yes
fi
Como posso fazer isso corretamente?
Preciso ainda combinar expressões para verificar se o HOST é "user1" ou começa com "node"
if [ [[ $HOST == user1 ]] -o [[ $HOST == node* ]] ];
then
echo yes
fi
> > > -bash: [: too many arguments
Como posso fazer isso corretamente?
string
bash
comparison
Tim
fonte
fonte
Respostas:
Este snippet no Advanced Bash Scripting Guide diz:
Então você quase acertou; você precisava de colchetes duplos , não de colchetes simples.
Com relação à sua segunda pergunta, você pode escrevê-lo desta maneira:
Qual eco
if
É difícil se acostumar com a sintaxe do Bash (IMO).fonte
[[ $a == z* ]]
e[[ $a == "z*" ]]
? Em outras palavras: eles funcionam de maneira diferente? E o que você quer dizer especificamente quando diz "$ a é igual a z *"?[[ $a == *com ]]
Se você estiver usando uma versão recente do Bash (v3 +), sugiro o operador de comparação de expressões regulares do Bash
=~
, por exemplo,Para corresponder a
this or that
uma regex, use|
, por exemplo,Nota - esta é uma sintaxe de expressão regular 'adequada'.
user*
significause
e zero ou mais ocorrências der
, portanto,use
euserrrr
corresponderão.user.*
médiasuser
e zero ou mais ocorrências de qualquer caractere, portantouser1
,userX
corresponderão.^user.*
significa corresponder ao padrãouser.*
no início de $ HOST.Se você não estiver familiarizado com a sintaxe da expressão regular, tente consultar este recurso .
fonte
=~
operador Bash apenas faz a correspondência de expressões regulares quando o lado direito não está cotado. Se você citar o lado direito "Qualquer parte do padrão pode ser citada para forçá-lo a corresponder como uma sequência". (1.) sempre coloque as expressões regulares à direita entre aspas e (2.) se você armazenar sua expressão regular em uma variável, certifique-se de NÃO citar o lado direito ao fazer a expansão de parâmetros.Eu sempre tento manter o POSIX em
sh
vez de usar extensões Bash, pois um dos principais pontos de script é a portabilidade (além de conectar programas, não substituí-los).Em
sh
, existe uma maneira fácil de verificar uma condição "é prefixo".Dada a idade, o arcano e o crocante sh (e o Bash não é a cura: é mais complicado, menos consistente e menos portátil), eu gostaria de destacar um aspecto funcional muito agradável: embora alguns elementos de sintaxe
case
sejam incorporados , as construções resultantes não são diferentes de qualquer outro trabalho. Eles podem ser compostos da mesma maneira:Ou ainda mais curto
Ou ainda mais curto (apenas para apresentar
!
como um elemento de linguagem - mas esse é um estilo ruim agora)Se você gosta de ser explícito, crie seu próprio elemento de linguagem:
Isso não é realmente muito bom?
E como
sh
são basicamente apenas trabalhos e listas de strings (e processos internamente, dos quais os trabalhos são compostos), agora podemos fazer alguma programação funcional leve:Isso é elegante. Não que eu advogasse o uso
sh
de algo sério - ele quebra muito rapidamente os requisitos do mundo real (sem lambdas, portanto, devemos usar strings. Mas aninhar chamadas de função com strings não é possível, tubos não são possíveis, etc.)fonte
case $HOST in user01 | node* ) ...
if case $HOST in node*) true;; *) false;; esac; then
Eu já vi isso aqui e ali, aos meus olhos parece meio amassado.case
comandos Becaues são comandos, eles podem entrarif ... then
.beginswith() { case "$2" in "$1"*) true;; *) false;; esac; }
diferente se$1
tiver um literal*
ou?
pode dar uma resposta errada.Você pode selecionar apenas a parte da sequência que deseja verificar:
Para sua pergunta de acompanhamento, você pode usar um OR :
fonte
${HOST:0:4}
HOST='a b'; if [ ${HOST:0:4} = user ] ; then echo YES ; fi
Eu prefiro os outros métodos já publicados, mas algumas pessoas gostam de usar:
Editar:
Adicionei seus suplentes à declaração de caso acima
Na sua versão editada, você tem muitos colchetes. Deve ficar assim:
fonte
Embora eu ache a maioria das respostas aqui bastante corretas, muitas delas contêm bashismos desnecessários. A expansão do parâmetro POSIX oferece tudo o que você precisa:
e
${var#expr}
retira o menor correspondente prefixoexpr
a partir${var}
e que retorna. Portanto, se${host}
é que não começar comuser
(node
),${host#user}
(${host#node}
) é o mesmo que${host}
.expr
permitefnmatch()
curingas, portanto,${host#node??}
e amigos também funcionam.fonte
[[ $host == user* ]]
pode ser necessário, já que é muito mais legível do que[ "${host#user}" != "${host}" ]
. Como tal, desde que você controle o ambiente em que o script é executado (segmente as versões mais recentesbash
), o primeiro é preferível.has_prefix()
função e nunca mais a veria .Como
#
tem um significado no Bash, cheguei à seguinte solução.Além disso, eu gosto mais de empacotar strings com "" para superar espaços, etc.
fonte
blah:
, parece que esta é a resposta!Adicionando um pouco mais de detalhes de sintaxe à resposta de classificação mais alta de Mark Rushakoff.
A expressão
Também pode ser escrito como
O efeito é o mesmo. Apenas verifique se o curinga está fora do texto citado. Se o curinga estiver dentro das aspas, ele será interpretado literalmente (ou seja, não como curinga).
fonte
@OP, para ambas as perguntas, você pode usar case / esac:
Segunda questão
Or Bash 4.0
fonte
;&
só está disponível no Bash> = 4.não funciona, porque todos
[
,[[
etest
reconhecer a mesma gramática não recursiva. Consulte a seção EXPRESSÕES CONDICIONAIS na sua página de manual do Bash.Como um aparte, o SUSv3 diz
Você precisaria escrever dessa maneira, mas o teste não suporta:
test usa = para igualdade de strings e, mais importante, não suporta correspondência de padrões.
case
/esac
tem um bom suporte para correspondência de padrões:Ele tem o benefício adicional de não depender do Bash, e a sintaxe é portátil. Na especificação Unix única , a linguagem de comandos do shell :
fonte
[
etest
são Bash builtins, bem como programas externos. Tentetype -a [
.if [ -z $aa -or -z $bb ]
; ... dá " bash: [: -ou: operador binário esperado "; no entantoif [ -z "$aa" -o -z "$bb" ] ; ...
passa.grep
Esquecendo o desempenho, este é o POSIX e parece melhor do que as
case
soluções:Explicação:
printf '%s'
impedir aprintf
expansão de escapes de barra invertida: Bash printf literal verbatim stringgrep -q
impede o eco de correspondências no stdout: como verificar se um arquivo contém uma sequência específica usando o Bashgrep -E
permite expressões regulares estendidas, necessárias para o^
fonte
Ajustei a resposta de @ markrushakoff para torná-la uma função que pode ser chamada:
Use-o assim:
Aqui está uma versão mais complexa que fornece um valor padrão especificado:
Use-o assim:
fonte
Outra coisa que você pode fazer é
cat
descobrir o que está ecoando e canalizarinline cut -c 1-1
fonte