bash: testaa, onko $ WORD joukossa

Etsin rakennetta bash, päättää onko muuttuja $WORD on määriteltyjä sanoja. Tarvitsen jotain tällaista:

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

onko bashilla tällainen rakenne? Jos ei, mikä olisi lähin?

Vastaus

Tämä on vain Bash-ratkaisu (> = versio 3), joka käyttää säännöllisiä lausekkeita:

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

Jos sanaluettelosi on pitkä, voit tallentaa sen tiedostoon (yksi sana riviä kohden) ja tehdä näin:

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

Yksi varoitus tiedostotavalla:

  • Se rikkoo, jos tiedostossa on tyhjää tilaa. Tämä voidaan korjata esimerkiksi:

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

Kiitos @terdonille, joka muistutti minua kiinnittämään kuvio oikein ^ ja $.

Kommentit

  • Ja shopt -s nocasematch voi auttaa, jos haluat haun olevan kirjainkoko.
  • Huomaa, että sinun on käytettävä [[ ja ]][ ja ] eivät riitä.
  • Etsin ’ onelinerille ’ skripti-argumenttini vahvistamiseksi, ja tämä toimi täydellisesti. Kiitos! [[ "$ARG" =~ ^(true|false)$ ]] || { echo "Argument received invalid value" ; exit 1 ; }
  • Jos ’ laitat osumaluettelosi tiedostoon, voit myös käyttää grep: egrep -q "^$WORD$" /tmp/words; [[ $? != 0 ]] && echo "Not found" || echo "OK".

Vastaa

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

Vastaus

Entä:

#!/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" 

Sitten:

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

vastaus

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

Kommentit

  • Huolellisesti, tämä palauttaa arvon tosi, jos $WORD on tyhjä, se vastaa, jos WORD=ca tai WORD=og tai vastaavaa, ja oletan, että tarkoitit echo ${set[@]}.
  • lisää vain -w grepiin osittaisten sanojen välttämiseksi

Vastaus

Voit määrittää tälle bash-funktion:

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

Käytä sitten yksinkertaisesti näin:

word_valid cat 

Vastaa

Etsin ”yksi rivi” -ratkaisua skripti-argumenttini vahvistamiseksi ja käytin yllä olevaa Joseph R. -vastausta . ylöspäin:

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

Vastaa

Sinä voisi käyttää fgrep-tiedostoa kaikkien sallittujen sanojen määrittämiseen:

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

Lippu -w vastaa vain kokonaisia sanoja, -q -lippu saa sen toimimaan äänettömästi (koska tarvitsemme vain if-käskyn palautusarvon), ja jokainen -e -malli määrittää mallin sallia.

fgrep on grep-versio, joka suorittaa normaalin merkkijonovastaavuuden regex-vastaavuuden sijaan. Jos sinulla on grep, sinulla pitäisi olla fgrep, mutta jos ei, se on identtinen grep -F -lipulla (joten korvaisit yllä olevan fgrep -wq vain grep -Fwq).

Vastaus

Tämä toimi minulle:

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

Vastaa

Voit lisätä sanaluettelon tiedostoon, jos muutat luetteloa usein tai haluat sen jakaa useita komentosarjoja. Ja sinun on ehkä laitettava sanat tiedostoon, jos luettelon hallinta on liian pitkä hallita komentosarjassa. Sitten voit sanoa

if fgrep –qx "$WORD" word_list 

Kommentit

  • ei, en halua ’ halua luetteloni olevan tiedostossa

Vastaa

Jos sanat ovat luettelo, jossa arvot erotetaan uudella rivillä, voit tehdä seuraavaa:

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

Vastaus

Minulla oli juuri sama ongelma ja löysin yllättävän ymmärrettävän ratkaisun, joka ei vaadi regex-tuntemusta.

Huomaa, että alla esitetty ratkaisu saattaa olla vain bash, koska minulla ei ole aavistustakaan bashin ja muiden kuorien välisistä eroista. Lisäksi bash-käsikirja varoittaa, että tällainen kuvion sovitus on hidasta, jos vastaava merkkijono on pitkä.

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

Kuinka tämä toimii?En halua toistaa tässä suuria osia bash-käsikirjasta, mutta omin sanoin:

Jos binaarioperaattoria == käytetään yhdistekomennon kanssa [[, operaattorin oikealla puolella olevalle sanalle tehdään kuvien sovitus, kuten osiossa ” kuvataan ” bash-käsikirjassa. Lisäksi näissä olosuhteissa, kun sovitetaan, kuorivaihtoehdon extglob oletetaan olevan asetettu (todellisesta asetuksesta riippumatta); tämä on avainasemassa yllä olevan ymmärtämisessä.

Mutta entä jos joukossasi olevat sanat sisältävät jo merkkejä, joilla on erityinen merkitys mallien sovituksessa, komentojen korvaamisessa ja muissa laajennuksissa? Korjauskeino on helppoa: Käytä vain jotain

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

Minusta tämä oli erittäin helppoa, ymmärrettävää ja tehokasta (kunhan $WORD on lyhyt) liuos, jolla ei ole sivuvaikutuksia tai joka on da epämiellyttäviä kuten set -pohjaiset menetelmät.

Vastaa

Sähköpostiosoitettasi ei julkaista. Pakolliset kentät on merkitty *