bash: test of $ WORD in set

ik ben op zoek naar een construct in bash, om te beslissen of een variabele $WORD is een van de gedefinieerde woorden. Ik heb zoiets als dit nodig:

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

heeft bash zon constructie? Zo niet, wat zou het dichtst in de buurt komen?

Answer

Dit is een alleen Bash (> = versie 3) oplossing die gebruikt reguliere expressies:

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

Als uw woordenlijst lang is, kunt u deze opslaan in een bestand (één woord per regel) en dit doen:

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

Een voorbehoud bij de bestandsbenadering:

  • Het zal breken als het bestand witruimte heeft. Dit kan worden verholpen door zoiets als:

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

Dank aan @terdon voor het eraan herinneren dat ik het patroon goed moet verankeren met ^ en $.

Reacties

  • En shopt -s nocasematch kan helpen als u wilt dat de zoekopdracht niet hoofdlettergevoelig is.
  • Merk op dat u [[ en ]][ en ] zijn niet genoeg.
  • ik was aan het zoeken voor een ‘ oneliner ‘ om mijn scriptargument te valideren, en dit werkte perfect. dank je! [[ "$ARG" =~ ^(true|false)$ ]] || { echo "Argument received invalid value" ; exit 1 ; }
  • Als u ‘ uw lijst met overeenkomsten in een bestand wilt plaatsen, kunt u net zo goed gebruiken grep: egrep -q "^$WORD$" /tmp/words; [[ $? != 0 ]] && echo "Not found" || echo "OK".

Antwoord

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

Antwoord

Hoe zit het met:

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

Vervolgens:

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

Antwoord

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

Reacties

  • Pas echter op, dit zal true retourneren als $WORD leeg is, het komt overeen als WORD=ca of WORD=og of iets dergelijks en ik neem aan dat je echo ${set[@]} bedoelde.
  • voeg gewoon toe -w naar grep om gedeeltelijke woorden te vermijden

Answer

Je zou hiervoor een bash-functie kunnen definiëren:

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

Gebruik dan gewoon zo:

word_valid cat 

Antwoord

ik was op zoek naar een “één regel” -oplossing om mijn scriptargument te valideren, en gebruikte Joseph R. antwoord hierboven om te komen op met:

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

Antwoord

Jij zou fgrep kunnen gebruiken om alle toegestane woorden te specificeren:

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

De -w vlag komt alleen overeen met volledige woorden, de -q vlag zorgt ervoor dat het stil werkt (omdat we alleen de retourwaarde nodig hebben om de if-instructie te gebruiken), en elk -e patroon specificeert een patroon toe te staan.

fgrep is de versie van grep die normale string-matching uitvoert in plaats van regex-matching. Als je grep hebt, zou je fgrep moeten hebben, maar zo niet, dan is het identiek aan het gebruik van grep met de -F vlag (dus je zou fgrep -wq hierboven vervangen door grep -Fwq).

Antwoord

Dit werkte voor mij:

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

Antwoord

Misschien wilt u de lijst met woorden in een bestand plaatsen, voor het geval u de lijst vaak wijzigt, of u wilt dat worden gedeeld door meerdere scripts. En mogelijk moet u de woorden in een bestand plaatsen als de lijst te lang wordt om in een script te beheren. Dan kunt u zeggen:

if fgrep –qx "$WORD" word_list 

Reacties

  • nee, ik wil niet ‘ mijn lijst in een bestand hebben

Answer

Als woorden een lijst zijn waarin waarden worden gescheiden door een nieuwe regel, kunt u het volgende doen:

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

Answer

Ik had net hetzelfde probleem en vond een verrassend begrijpelijke oplossing waarvoor geen kennis van regex vereist is.

Houd er rekening mee dat de De onderstaande oplossing is mogelijk alleen bash, omdat ik geen idee heb van de verschillen tussen bash en andere shells. Verder waarschuwt de bash-handleiding dat dit soort patroonafstemming traag is als de string die moet worden aangepast lang is.

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

Hoe werkt dit?Ik wil hier geen grote delen van de bash-handleiding herhalen, maar in mijn eigen woorden:

Als de binaire operator == wordt gebruikt met het samengestelde commando [[, het woord aan de rechterkant van de operator ondergaat patroonovereenkomst zoals uitgelegd in de sectie ” Patroonovereenkomst ” in de bash-handleiding. Verder wordt onder deze omstandigheden, tijdens het matchen, aangenomen dat de shell-optie extglob is ingesteld (ongeacht de feitelijke instelling); dit is het belangrijkste punt om het bovenstaande te begrijpen.

Maar wat als de woorden in uw set al tekens bevatten die een speciale betekenis hebben bij het matchen van patronen, het vervangen van opdrachten en andere uitbreidingen? De oplossing is eenvoudig: gebruik gewoon zoiets als

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

Ik vond dit een zeer gemakkelijke, begrijpelijke en efficiënte (zolang $WORD kort is) oplossing die geen bijwerkingen heeft of da is kwaadaardig zoals de set -gebaseerde methoden.

Geef een reactie

Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *