Následující bash syntaxe ověřuje, zda param
není prázdný:
[[ ! -z $param ]]
Například:
param="" [[ ! -z $param ]] && echo "I am not zero"
Žádný výstup a jeho pokuta.
Ale když param
je prázdný s výjimkou jednoho (nebo více) mezer, pak je případ jiný:
param=" " # one space [[ ! -z $param ]] && echo "I am not zero"
„Nejsem nula „je na výstupu.
Jak mohu změnit test tak, aby považoval proměnné, které obsahují pouze mezery, za prázdné?
Komentáře
- From
man test
:-z STRING - the length of STRING is zero
. Pokud chcete odstranit všechny mezery v$param
, použijte${param// /}
- WOW neexistuje jednoduchá funkce
trim()
jakýkoli * nix vůbec? Tolik různých hacků k dosažení něčeho tak jednoduchého … - @ADTC $ (sed ‚ s / ^ \ s + | \ s + $ // g ‚ < < < $ string) se mi zdá dost jednoduchý. Proč znovu objevovat kolo?
- Protože by to mohlo být lesklejší
- Jen poznamenám, že
[[ ! -z $param ]]
je ekvivalentní stest ! -z $param
.
Odpověď
Nejprve si všimněte, že -z
test je výslovně určen pro:
délka řetězce je nula
To znamená, že řetězec obsahující pouze mezery by neměl být pravdivý pod -z
, protože má nenulovou délku.
To, co chcete, je odstranit mezery z proměnné pomocí rozšíření parametrů nahrazení vzoru :
[[ -z "${param// }" ]]
Tím se rozšíří param
a nahradí všechny shody vzoru (jedna mezera) ničím, takže řetězec, který obsahuje pouze mezery, bude rozbalen na prázdný řetězec.
hloupost toho, jak to funguje , je ${var/pattern/string}
nahrazuje první nejdelší shodu pattern
za string
. Když pattern
začíná /
(jak je uvedeno výše), nahradí všechny shody. Protože náhrada je prázdná, můžeme vynechat konečnou /
a string
hodnotu:
$ {parametr / vzor / řetězec}
Vzor se rozbalí a vytvoří vzor stejně jako v rozšíření názvu souboru. Parametr se rozbalí a nejdelší shoda vzoru s jeho hodnotou se nahradí řetězcem . Pokud vzor začíná na „/“, všechny shody vzoru jsou nahrazeny řetězcem . Normálně je nahrazen pouze první zápas. … Pokud řetězec má hodnotu null, budou odstraněny shody vzoru a / následující vzor může být vynechán.
Po tom všem skončíme s ${param// }
smazáním všech mezer.
Pamatujte však, že přítomné v ksh
(odkud pochází), zsh
a bash
, tato syntaxe není POSIX a neměl by se používat ve sh
skriptech.
Komentáře
Odpověď
Snadný způsob zkontrolovat, zda řetězec obsahuje pouze znaky v autorizované sadě, je otestovat přítomnost neautorizovaných znaků.Takže místo testování, zda řetězec obsahuje pouze mezery, otestujte, zda řetězec obsahuje jiný znak než mezeru. V bash, ksh nebo zsh:
if [[ $param = *[!\ ]* ]]; then echo "\$param contains characters other than space" else echo "\$param consists of spaces only" fi
„Skládá se pouze z mezer“ zahrnuje případ prázdné (nebo zrušené) proměnné.
Možná budete chtít otestovat jakýkoli prázdný znak. Pomocí [[ $param = *[^[:space:]]* ]]
použijte nastavení národního prostředí nebo jakýkoli explicitní seznam mezer, které chcete otestovat, např. [[ $param = *[$" \t\n"]* ]]
k testování prostoru, tabulátoru nebo nového řádku.
Porovnání řetězce se vzorem s =
uvnitř [[ … ]]
je přípona ksh (také přítomná v bash a zsh). V jakémkoli stylu Bourne / POSIX můžete použít konstrukci case
k porovnání řetězce se vzorem. Všimněte si, že standardní vzory prostředí používají !
k negaci znakové sady, místo ^
jako ve většině syntaxí regulárních výrazů.
case "$param" in *[!\ ]*) echo "\$param contains characters other than space";; *) echo "\$param consists of spaces only";; esac
Chcete-li otestovat prázdné znaky, je syntaxe $"…"
specifická pro ksh / bash / zsh; můžete tyto znaky vložit do svého skriptu doslovně (všimněte si, že nový řádek bude muset být v uvozovkách, protože zpětné lomítko + nový řádek se rozšiřuje na nic), nebo je generovat, např.
whitespace=$(printf "\n\t ") case "$param" in *[!$whitespace]*) echo "\$param contains non-whitespace characters";; *) echo "\$param consists of whitespace only";; esac
Komentáře
- To je téměř vynikající – zatím však na otázku neodpovídá tak, jak byla položena. V současné době vám může říci rozdíl mezi zrušenou nebo prázdnou proměnnou shellu a jednou, která obsahuje pouze mezery. Pokud přijmete můj návrh, přidáte formulář pro rozšíření parametrů, který ještě nebyl převeden jinou odpovědí, která explicitně testuje proměnnou prostředí pro nastavení – myslím
${var?not set}
– absolvování tohoto testu a přežití zajistí, že proměnná odpovídající vašemu*)
case
bude mít například konečnou odpověď. - Oprava – to by ve skutečnosti odpovědělo na původně položenou otázku, ale od té doby byla upravena takovým způsobem, že zásadně mění význam otázky, a proto zneplatňuje vaši odpověď.
- Potřebujete
[[ $param = *[!\ ]* ]]
vmksh
.
Odpovědět
POSIXly:
case $var in (*[![:blank:]]*) echo "$var contains non blank";; (*) echo "$var contains only blanks or is empty or unset" esac
Rozlišovat mezi prázdnými , neprázdnými , prázdný , zrušit :
case ${var+x$var} in (x) echo empty;; ("") echo unset;; (x*[![:blank:]]*) echo non-blank;; (*) echo blank esac
[:blank:]
je pro vodorovné mezery mezi znaky (mezera a karta v A SCII, ale ve vašem národním prostředí je pravděpodobně několik dalších; některé systémy budou obsahovat nerozbitný prostor (pokud je k dispozici), některé nebudou „t“. Pokud chcete také znaky se svislými mezerami (například nový řádek nebo form-feed), nahraďte [:blank:]
s [:space:]
.
Komentáře
- POSIXly je ideální, protože bude fungovat s (pravděpodobně lepšími) pomlčka.
-
zsh
má zřejmě problém s[![:blank:]]
, zvyšuje:b
je neplatný modifikátor. V emulacish
aksh
vyvolá událost, která nebyla nalezena pro[
- @cuonglm, co jste vyzkoušeli?
var=foo zsh -c 'case ${var+x$var} in (x*[![:blank:]]*) echo x; esac'
je pro mě v pořádku. Nenalezená událost by byla pouze pro interaktivní skořápky. - @St é phaneChazelas: Aha, zkusil jsem to s interaktivními mušlemi.
:b
neplatný modifikátor je trochu divný. - @FranklinYu, na OS / X
sh
je postavený s--enable-xpg-echo-default
a--enable-strict-posix-default
tak, aby vyhovoval Unixu (což zahrnujeecho '\t'
výstup na kartu).
Odpověď
Jediný zbývající důvod k psaní shell skript, místo skriptu ve dobrém skriptovacím jazyce, je, pokud převažuje extrémní přenositelnost. Starší /bin/sh
je jediná věc, kterou si můžete být jisti, že máte, ale například Perl je častěji pravděpodobně dostupný napříč platformami než Bash. Proto nikdy nepište shell skripty, které používají funkce, které nejsou skutečně univerzální – a mějte na paměti, že několik vlastních prodejců Unixu zmrazilo jejich prostředí prostředí před POSIX.1-2001 .
Existuje tento přenosný způsob provedení tohoto testu, ale musíte použít tr
:
[ "x`printf "%s" "$var" | tr -d "$IFS"`" = x ]
(Výchozí hodnota $IFS
je pohodlně mezera, karta a nový řádek.)
(printf
builtin je sám o sobě skvostně přenosný, ale spoléhat se na něj je mnohem méně potíží než zjišťovat, kterou variantu echo
máte.)
Komentáře
- To je ‚ spletité.Obvyklým přenosným způsobem, jak otestovat, zda řetězec obsahuje určité znaky, je s
case
. - @Gilles Nemyslím si ‚ že ‚ je možné napsat
case
glob do detekovat řetězec, který je buď prázdný, nebo obsahuje pouze mezery. (S regexpem by to bylo snadné, alecase
nedělá ‚ regexps. Konstrukt ve vaší odpovědi nevyhrál ‚ nefunguje, pokud vám záleží na nových řádcích.) - V odpovědi jsem uvedl mezery jako příklad, protože to je otázka ‚ požádal o. Stejně snadné je ‚ otestovat prázdné znaky:
case $param in *[![:space:]]*) …
. Pokud chcete otestovatIFS
znaků, můžete použít vzor*[$IFS]*
. - @mikeserv Opravdu vážně obranný skript, na začátku explicitně nastavíte IFS na
<space><tab><newline>
a už se ho nikdy nedotknete. Myslel jsem, že ‚ d bude odvádět pozornost. - Co se týče proměnných ve vzorcích, myslím, že to funguje ve všech verzích Bourne a ve všech skořápkách POSIX; vyžadovalo by to další kód pro detekci vzorů případů a vypnutí expanze proměnných a nemohu ‚ vymyslet důvod, proč to udělat. Mám několik instancí ve svém
.profile
, který byl proveden mnoha Bourneovými granáty. Samozřejmě[$IFS]
nebude ‚ dělat to, co bylo zamýšleno, pokudIFS
má určité jiné než výchozí hodnoty (prázdné (nebo zrušené), obsahující]
, začínající!
nebo^
) .
Odpověď
if [[ -n "${variable_name/[ ]*\n/}" ]] then #execute if the the variable is not empty and contains non space characters else #execute if the variable is empty or contains only spaces fi
Komentáře
- tím se zbavíte jakéhokoli znaku prázdného místa, nejen jednoho mezery, že? děkuji
odpověď
Pro testování, zda je proměnná prázdná nebo obsahuje mezery, můžete také použít tento kód:
${name:?variable is empty}
Komentáře
- Myslím, že vaše odpověď je odmítnuta, protože “ nebo obsahovat mezery “ není pravda.
- buďte opatrní – to zabije aktuální shell. Lepší je dát to do (: $ {subshell?}). Také – to zapíše stderr – pravděpodobně budete chtít přesměrovat. A nejdůležitější , která se vyhodnotí na skutečnou hodnotu proměnné ‚, pokud není nastavená nebo null. Pokud je tam ‚ příkaz, spustili jste ho. ‚ Nejlepší je spustit tento test na
:
. - jak zabije shell. a můžete to také otestovat, nejprve definujte
name=aaaa
a poté spusťte tento příkazecho ${name:?variable is empty}
vypíše hodnotu názvu proměnné a nyní spusťte tento příkazecho ${name1:?variable is empty}
vytiskne -sh: name1: proměnná je prázdná - ano –
echo ${name:?variable is empty}
buď vyhodnotí na$name
‚ nenulovou hodnotu nebo zabije shell. Ze stejného důvodu tedy ‚ tprompt > $randomvar
neměli byste${var?}
– pokud tam je ‚ sa příkaz, ten ‚ pravděpodobně běží – a vy ‚ nevím, co to je. Interaktivní prostředí nemusí ‚ opustit – proto ten váš ‚ t. Pokud si přesto chcete prohlédnout některé testy, je jich zde spousta. Tento není ‚ tak dlouho …
Odpověď
Kód, který jste zveřejnili [[ ! -z $param ]] && echo "I am not zero"
vytiskne I am not zero
pokud parametr je buď nenastavený / nedefinovaný, nebo prázdný (v bash, ksh a zsh).
Do také tisknout, pokud parametr obsahuje pouze mezery (odstranit mezery), POSIXly (pro širší rozsah skořápek):
[ -z "${param#"${param%%[! ]*}"}" ] && echo "empty"
Vysvětlení:
- A
${param# … }
odebere úvodní text. - Tento úvodní text je dán:
${param%%[! ]*}
- který se rozšíří na všechny mezery před libovolný neprostorový znak, tj. Všechny úvodní mezery.
Konečným výsledkem celé expanze je odstranění všech předních mezer.
Tento rozšířený výsledek se testuje, pokud má délku 0.
- Pokud je výsledek prázdný, pak byla buď proměnná prázdná, nebo
- odstranění úvodních mezer udělal to prázdné.
Proto je-li test pravdivý, byla proměnná buď prázdná, nebo měla uvnitř pouze mezery.
Koncept lze snadno rozšířit na více typy znaků. Chcete-li zahrnout také karty, vložte explicitní kartu do výrazu závorky:
[ -z "${param#"${param%%[! ]*}"}" ] && echo "empty"
nebo použijte proměnnou se znaky, které potřebujete odstranit:
var=$" \t" # in ksh, bash, zsh [ -z "${param#"${param%%[!$var]*}"}" ] && echo "empty"
nebo můžete použít nějaký POSIX „výraz třídy znaků“ (prázdné znamená mezeru a tabulátor):
[ -z "${param#"${param%%[![:blank:]]*}"}" ] && echo "empty"
Odpověď
Chcete-li zkontrolovat, zda má proměnná pouze mezery, včetně víceřádkové proměnné , zkuste toto:
[[ $var = *[$" \t\n"]* ]]
Nebo s xargs:
[[ -z $(echo $var | xargs) ]]
Nebo se sed:
[[ -z $(sed "/^$/d" <<< $var) ]]
Odpověď
Zkuste toto:
$ [[ -z \`echo $n\` ]] && echo zero zero
sed
řekli … jenecho
proměnnou, kterou řekli …${var/pattern/string}
, nemělo by to být ‚ t[[ -z ${param/ /} ]]
s mezerou mezi lomítky být vzorem a nic poté, co být řetězcem?[[ -z "${param// }" ]]
určitě vypadá jakopattern
je prázdný areplacement string
je jeden prostor. AH! Vidím to nyníif pattern begins with a slash
Tuto část jsem zmeškal. vzor je tedy/
a řetězec je vynechán, a proto je prázdný. Díky.