Hledám konstrukt v bash
, abych se rozhodl, zda proměnná $WORD
je jedno z definovaných slov. Potřebuji něco takového:
if "$WORD" in dog cat horse ; then echo yes else echo no fi
má bash takový konstrukt? Pokud ne, jaké by bylo nejbližší?
Odpověď
Toto je řešení pouze pro Bash (> = verze 3), které používá regulární výrazy:
if [[ "$WORD" =~ ^(cat|dog|horse)$ ]]; then echo "$WORD is in the list" else echo "$WORD is not in the list" fi
Pokud je váš seznam slov dlouhý, můžete jej uložit do souboru (jedno slovo na řádek) a provést toto:
if [[ "$WORD" =~ $(echo ^\($(paste -sd"|" /your/file)\)$) ]]; then echo "$WORD is in the list" else echo "$WORD is not in the list" fi
Jedno upozornění s přístupem k souboru:
-
Rozbije se, pokud má soubor mezery. To lze napravit pomocí něčeho jako:
sed "s/[[:blank:]]//g" /your/file | paste -sd "|" /dev/stdin
Díky @terdon mi připomněl, abych správně ukotvil vzor pomocí ^
a $
.
Komentáře
odpověď
case $word in dog|cat|horse) echo yes;; *) echo no;; esac
Odpověď
Co takhle:
#!/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"
Potom:
$ a.sh cat cat is in the list $ a.sh bob bob is not in the list
Odpovědět
if (echo "$set" | fgrep -q "$WORD")
Komentáře
- Opatrně, toto vrátí hodnotu true, pokud je
$WORD
prázdný, bude odpovídat, pokudWORD=ca
neboWORD=og
nebo podobné a předpokládám, že jste mysleliecho ${set[@]}
. - stačí přidat -w to grep, aby se zabránilo neúplným slovům
Odpovědět
K tomu můžete definovat funkci bash:
function word_valid() { if [ "$1" != "cat" -a "$1" != "dog" -a "$1" != "horse" ];then echo no else echo yes fi }
Pak použijte jednoduše takto:
word_valid cat
Odpovědět
Hledal jsem „jednořádkové“ řešení k ověření argumentu mého skriptu a použil jsem Joseph R. answer výše nahoru s:
[[ "$ARG" =~ ^(true|false)$ ]] || { echo "Argument received invalid value" ; exit 1 ; }
Odpověď
Vy mohl použít fgrep k určení všech povolených slov:
if $(echo "$WORD" | fgrep -wq -e dog -e cat -e horse) ; then echo yes else echo no fi
Příznak -w
odpovídá pouze plným slovům, -q
příznak umožňuje tichý provoz (protože potřebujeme pouze návratovou hodnotu příkazu if) a každý -e
vzor určuje vzor povolit.
fgrep
je verze grepu, která místo shody s regulárním výrazem provádí normální shodu řetězců. Pokud máte grep
, měli byste mít fgrep
, ale pokud ne, je to stejné jako použití grep
s příznakem -F
(stačí tedy fgrep -wq
výše nahradit grep -Fwq
).
Odpověď
Toto pro mě fungovalo:
#!/bin/bash phrase=(cat dog parrot cow horse) findthis=parrot for item in ${phrase[*]} do test "$item" == "$findthis" && { echo "$findthis found!"; break; } done
Odpověď
Možná budete chtít vložit seznam slov do souboru, pokud jej často měníte nebo chcete být sdíleny více skripty. A pokud bude seznam příliš dlouhý na správu ve skriptu, možná budete muset slova vložit do souboru. Potom můžete říci
if fgrep –qx "$WORD" word_list
Komentáře
- ne, ‚ nechci mít svůj seznam v souboru
Odpověď
Pokud jsou slova seznamem, kde jsou hodnoty odděleny novým řádkem, můžete:
WORDS="$(ls -1)" if echo "${WORDS}" | grep --quiet --line-regexp --fixed-strings "${WORD}"; then echo yes else echo no fi
Odpověď
Právě jsem měl stejný problém a našel jsem překvapivě srozumitelné řešení, které nevyžaduje žádné znalosti regulárního výrazu.
Upozorňujeme, že níže zobrazené řešení může být pouze bash, protože nemám ponětí o rozdílech mezi bash a jinými mušlemi. Manuál bash dále varuje, že tento druh porovnávání vzorů je pomalý, pokud je řetězec, který by měl odpovídat, dlouhý.
WORD=abc [[ "$WORD" == @(def|abc|ghi|foo|barbaz) ]] && echo Word is in set.
Jak to funguje?Nechci zde opakovat velké části příručky bash, ale podle mých vlastních slov:
Pokud je použit binární operátor ==
s složeným příkazem [[
, slovo na pravé straně operátoru prochází porovnáváním vzorů, jak je vysvětleno v sekci “ Porovnávání vzorů “ v příručce bash. Dále se za těchto podmínek při párování předpokládá, že je nastavena volba prostředí extglob
(bez ohledu na skutečné nastavení); toto je klíčový bod pro pochopení výše uvedeného.
Ale co když slova ve vaší sadě již obsahují znaky, které mají zvláštní význam pro porovnávání vzorů, nahrazování příkazů a další rozšíření? Náprava je snadná: Stačí použít něco jako
[[ "$WORD" == @("a*"|abc|"?ghi"|"$DontExpandMe"|barbaz) ]] && echo Word is in set.
Zjistil jsem, že je to velmi snadné, srozumitelné a efektivní (pokud je $WORD
krátký) řešení, které nemá vedlejší účinky nebo je da bláznivé jako metody založené na set
.
shopt -s nocasematch
může pomoci, pokud chcete, aby vyhledávání nerozlišovalo velká a malá písmena.[[
a]]
–[
a]
nestačí.[[ "$ARG" =~ ^(true|false)$ ]] || { echo "Argument received invalid value" ; exit 1 ; }
egrep -q "^$WORD$" /tmp/words; [[ $? != 0 ]] && echo "Not found" || echo "OK"
.