bash: verifica se $ WORD è nel set

Sto cercando un costrutto in bash, per decidere se una variabile $WORD è una delle parole definite. Ho bisogno di qualcosa del genere:

if "$WORD" in dog cat horse ; then echo yes else echo no fi 

bash ha un tale costrutto? In caso contrario, quale sarebbe la più vicina?

Risposta

Questa è una soluzione solo Bash (> = versione 3) che utilizza espressioni regolari:

if [[ "$WORD" =~ ^(cat|dog|horse)$ ]]; then echo "$WORD is in the list" else echo "$WORD is not in the list" fi 

Se il tuo elenco di parole è lungo, puoi memorizzarlo in un file (una parola per riga) e fare così:

if [[ "$WORD" =~ $(echo ^\($(paste -sd"|" /your/file)\)$) ]]; then echo "$WORD is in the list" else echo "$WORD is not in the list" fi 

Un avvertimento con lapproccio file:

  • Si interromperà se il file ha spazi bianchi. Questo può essere risolto con qualcosa del tipo:

    sed "s/[[:blank:]]//g" /your/file | paste -sd "|" /dev/stdin 

Grazie a @terdon per avermi ricordato di ancorare correttamente lo schema con ^ e $.

Commenti

  • E shopt -s nocasematch potrebbe essere utile se desideri che la ricerca non faccia distinzione tra maiuscole e minuscole.
  • Tieni presente che devi utilizzare [[ e ]][ e ] non sono sufficienti.
  • Stavo cercando per un ‘ oneliner ‘ per convalidare il mio argomento dello script, e questo ha funzionato perfettamente. grazie! [[ "$ARG" =~ ^(true|false)$ ]] || { echo "Argument received invalid value" ; exit 1 ; }
  • Se ‘ inserirai il tuo elenco di corrispondenze in un file, potresti anche utilizzare grep: egrep -q "^$WORD$" /tmp/words; [[ $? != 0 ]] && echo "Not found" || echo "OK".

Risposta

case $word in dog|cat|horse) echo yes;; *) echo no;; esac 

Risposta

Che ne dici di:

#!/usr/bin/env bash WORD="$1" for w in dog cat horse do if [ "$w" == "$WORD" ] then yes=1 break fi done; [ "$yes" == "1" ] && echo "$WORD is in the list" || echo "$WORD is not in the list" 

Quindi:

$ a.sh cat cat is in the list $ a.sh bob bob is not in the list 

Rispondi

if (echo "$set" | fgrep -q "$WORD") 

Commenti

  • Attenzione però, questo restituirà true se $WORD è vuoto, corrisponderà se WORD=ca o WORD=og o simili e presumo che tu intendessi echo ${set[@]}.
  • aggiungi semplicemente -w a grep per evitare parole parziali

Answer

Potresti definire una funzione bash per questo:

function word_valid() { if [ "$1" != "cat" -a "$1" != "dog" -a "$1" != "horse" ];then echo no else echo yes fi } 

Quindi usa semplicemente in questo modo:

word_valid cat 

Risposta

stavo cercando una soluzione “una riga” per convalidare largomento del mio script e ho utilizzato Joseph R. answer qui sopra con:

[[ "$ARG" =~ ^(true|false)$ ]] || { echo "Argument received invalid value" ; exit 1 ; }

Risposta

Tu potrebbe utilizzare fgrep per specificare tutte le parole consentite:

if $(echo "$WORD" | fgrep -wq -e dog -e cat -e horse) ; then echo yes else echo no fi 

Il flag -w corrisponde solo alle parole intere, il -q il flag lo fa funzionare silenziosamente (perché tutto ciò di cui abbiamo bisogno è il valore di ritorno per listruzione if da utilizzare) e ogni -e pattern specifica un pattern per consentire.

fgrep è la versione di grep che esegue la normale corrispondenza delle stringhe invece della corrispondenza regolare. Se hai grep, dovresti avere fgrep, ma in caso contrario, “è identico a utilizzare grep con il flag -F (quindi dovresti semplicemente sostituire fgrep -wq sopra con grep -Fwq).

Risposta

Questo ha funzionato per me:

#!/bin/bash phrase=(cat dog parrot cow horse) findthis=parrot for item in ${phrase[*]} do test "$item" == "$findthis" && { echo "$findthis found!"; break; } done 

Risposta

Potresti voler inserire lelenco di parole in un file, nel caso in cui cambi lelenco spesso, o lo desideri essere condiviso da più script. E potresti dover inserire le parole in un file se lelenco diventa troppo lungo per essere gestito in uno script. Quindi puoi dire

if fgrep –qx "$WORD" word_list 

Commenti

  • no, non ‘ voglio avere il mio elenco in un file

Risposta

Se le parole sono un elenco in cui i valori sono separati da una nuova riga, puoi fare:

WORDS="$(ls -1)" if echo "${WORDS}" | grep --quiet --line-regexp --fixed-strings "${WORD}"; then echo yes else echo no fi 

Risposta

Ho appena avuto lo stesso problema e ho trovato una soluzione sorprendentemente comprensibile che non richiede alcuna conoscenza di regex.

Tieni presente che il la soluzione mostrata di seguito potrebbe essere solo bash, perché non ho idea delle differenze tra bash e altre shell. Inoltre, il manuale di bash avverte che questo tipo di corrispondenza di pattern è lento se la stringa che deve essere trovata è lunga.

WORD=abc [[ "$WORD" == @(def|abc|ghi|foo|barbaz) ]] && echo Word is in set. 

Come funziona?Non voglio ripetere qui grandi porzioni del manuale di bash, ma con parole mie:

Se loperatore binario == viene utilizzato con il comando composto [[, la parola a destra delloperatore viene sottoposta a corrispondenza di pattern come spiegato nella sezione ” Pattern di corrispondenza ” nel manuale di bash. Inoltre, in queste condizioni, durante la corrispondenza, si presume che lopzione shell extglob sia impostata (indipendentemente dallimpostazione effettiva); questa è il punto chiave per comprendere quanto sopra.

Ma cosa succede se le parole nel tuo set contengono già caratteri che hanno un significato speciale nella corrispondenza dei modelli, nella sostituzione dei comandi e in altre espansioni? Il rimedio è semplice: usa qualcosa come

[[ "$WORD" == @("a*"|abc|"?ghi"|"$DontExpandMe"|barbaz) ]] && echo Word is in set. 

Ho trovato molto semplice, comprensibile ed efficiente (purché $WORD sia breve) soluzione che non ha effetti collaterali o è da ngerous come i metodi basati su set.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *