Caut un construct în bash
, pentru a decide dacă o variabilă $WORD
este unul dintre cuvintele definite. Am nevoie de așa ceva:
if "$WORD" in dog cat horse ; then echo yes else echo no fi
are bash o astfel de construcție? Dacă nu, care ar fi cea mai apropiată?
Răspuns
Aceasta este o soluție Bash-only (> = versiunea 3) care folosește expresii regulate:
if [[ "$WORD" =~ ^(cat|dog|horse)$ ]]; then echo "$WORD is in the list" else echo "$WORD is not in the list" fi
Dacă lista de cuvinte este lungă, o puteți stoca într-un fișier (un cuvânt pe rând) și faceți acest lucru:
if [[ "$WORD" =~ $(echo ^\($(paste -sd"|" /your/file)\)$) ]]; then echo "$WORD is in the list" else echo "$WORD is not in the list" fi
Un avertisment cu abordarea fișierului:
-
Se va întrerupe dacă fișierul are spațiu alb. Acest lucru poate fi remediat prin ceva de genul:
sed "s/[[:blank:]]//g" /your/file | paste -sd "|" /dev/stdin
Mulțumesc lui @terdon că mi-a reamintit să ancorez corect modelul cu ^
și $
.
Comentarii
Răspuns
case $word in dog|cat|horse) echo yes;; *) echo no;; esac
Răspuns
Ce zici de:
#!/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"
Apoi:
$ a.sh cat cat is in the list $ a.sh bob bob is not in the list
Răspuns
if (echo "$set" | fgrep -q "$WORD")
Comentarii
- Cu toate acestea, cu atenție, acest lucru va reveni adevărat dacă
$WORD
este gol, se va potrivi dacăWORD=ca
sauWORD=og
sau similar și presupun că ai vrut să spuiecho ${set[@]}
. - adaugă -w la grep pentru a evita cuvintele parțiale
Răspuns
Puteți defini o funcție bash pentru aceasta:
function word_valid() { if [ "$1" != "cat" -a "$1" != "dog" -a "$1" != "horse" ];then echo no else echo yes fi }
Apoi utilizați pur și simplu așa:
word_valid cat
Răspuns
Căutam o soluție „cu o singură linie” pentru a valida argumentul meu de script și am folosit Joseph R. answer mai sus pentru a veni cu:
[[ "$ARG" =~ ^(true|false)$ ]] || { echo "Argument received invalid value" ; exit 1 ; }
Răspuns
Tu ar putea folosi fgrep pentru a specifica toate cuvintele permise:
if $(echo "$WORD" | fgrep -wq -e dog -e cat -e horse) ; then echo yes else echo no fi
Steagul -w
se potrivește numai cu cuvinte complete, -q
îl face să funcționeze silențios (pentru că tot ce avem nevoie este valoarea returnată pentru instrucțiunea if de utilizat) și fiecare model -e
specifică un model a permite.
fgrep
este versiunea grep care face potrivire normală de șiruri în loc de potrivire regex. Dacă aveți grep
, ar trebui să aveți fgrep
, dar dacă nu, este identic cu utilizarea grep
cu steagul -F
(deci ați înlocui doar fgrep -wq
de mai sus cu grep -Fwq
).
Răspuns
Acest lucru a funcționat pentru mine:
#!/bin/bash phrase=(cat dog parrot cow horse) findthis=parrot for item in ${phrase[*]} do test "$item" == "$findthis" && { echo "$findthis found!"; break; } done
Răspuns
Poate doriți să introduceți lista de cuvinte într-un fișier, în cazul în care modificați lista des sau doriți să să fie partajat de mai multe scripturi. Și poate fi necesar să introduceți cuvintele într-un fișier dacă lista devine prea lungă pentru a fi gestionată într-un script. Apoi puteți spune
if fgrep –qx "$WORD" word_list
Comentarii
- nu, nu ‘ nu vreau să am lista mea într-un fișier
Răspuns
Dacă cuvintele sunt o listă în care valorile sunt separate printr-o linie nouă, puteți face:
WORDS="$(ls -1)" if echo "${WORDS}" | grep --quiet --line-regexp --fixed-strings "${WORD}"; then echo yes else echo no fi
Răspuns
Tocmai am avut aceeași problemă și am găsit o soluție surprinzător de înțeleasă, care nu necesită cunoștințe regex.
Vă rugăm să rețineți că soluția prezentată mai jos ar putea fi doar bash, deoarece nu am nici o idee despre diferențele dintre bash și alte cochilii. Mai mult, manualul bash avertizează că acest tip de potrivire a modelelor este lent dacă șirul care ar trebui să fie asortat este lung.
WORD=abc [[ "$WORD" == @(def|abc|ghi|foo|barbaz) ]] && echo Word is in set.
Cum funcționează acest lucru?Nu vreau să repet porțiuni mari din manualul bash aici, dar în propriile mele cuvinte:
Dacă operatorul binar ==
este utilizat cu comanda compusă [[
, cuvântul din partea dreaptă a operatorului suferă potrivirea modelelor, așa cum se explică în secțiunea ” Potrivirea modelelor ” în manualul bash. În plus, în aceste condiții, în timp ce se potrivește, se presupune că opțiunea shell extglob
este setată (indiferent de setarea reală); aceasta este punctul cheie în înțelegerea celor de mai sus.
Dar ce se întâmplă dacă cuvintele din setul dvs. conțin deja caractere care au o semnificație specială în potrivirea modelelor, înlocuirea comenzilor și alte expansiuni? Remediul este ușor: folosiți doar ceva de genul
[[ "$WORD" == @("a*"|abc|"?ghi"|"$DontExpandMe"|barbaz) ]] && echo Word is in set.
Mi s-a părut foarte ușor, ușor de înțeles și eficient (atâta timp cât $WORD
este scurt) soluție care nu are efecte secundare sau este da ciudat ca metodele bazate pe set
.
shopt -s nocasematch
vă poate ajuta dacă doriți căutarea să nu distingă majuscule și minuscule.[[
și]]
–[
și]
nu sunt suficiente.[[ "$ARG" =~ ^(true|false)$ ]] || { echo "Argument received invalid value" ; exit 1 ; }
egrep -q "^$WORD$" /tmp/words; [[ $? != 0 ]] && echo "Not found" || echo "OK"
.