WebHU - Programozási kérdések és válaszok

Bash-ban van mód a változók kétszeres kiterjesztésére dupla idézőjelben?

A szkriptjeim hibakereséséhez minden kimenetem elejére szeretném hozzáadni a $FUNCNAME és a $LINENO belső változókat, hogy tudjam, melyik függvényen és sorszámon történik a kimenet.

foo(){
    local bar="something"
    echo "$FUNCNAME $LINENO: I just set bar to $bar"
}

De mivel sok hibakereső kimenet lesz, tisztább lenne, ha valami ilyesmit tennék:

foo(){
    local trace='$FUNCNAME $LINENO'
    local bar="something"
    echo "$trace: I just set bar to $bar"
}

De a fenti szó szerint a következőt adja ki: "$FUNCNAME $LINENO: Most állítottam rá valamit" Azt hiszem, ezt teszi, mert a dupla idézőjelek csak egyszer bővítik ki a változókat.

Van-e szintaktikailag tiszta módszer a változók kétszeri bővítésére ugyanabban a sorban?


  • Hoppá. Könnyű lenne, ha csak egy változónév szerepelne a változóban – ebben az esetben ez csak szabványos közvetett kiterjesztés. Ezzel szemben, ha ki akarunk bővíteni egy sablont tetszőleges számú változóval, akkor eval térbe kerülünk, ami nyilvánvalóan egyáltalán nem biztonságos. 26.05.2018
  • ez majdnem működik – ha local trace=FUNCNAME, akkor írhatna echo ${!trace} ": I just set bar to $bar" 26.05.2018
  • @codeforester ...ez elég kemény címszerkesztés. Teljesen eltávolítja a kontextust az (eredeti) válaszom tetején található egysoros összefoglalóból (f/e), és olyan válaszokat ad, amelyek nem foglalkoznak az OP közvetlen/azonnali kérdésével a bővítéssel kapcsolatban egyáltalán . 26.05.2018
  • Én is így gondoltam... Most, hogy elmeséled, csak visszaforgattam. 26.05.2018

Válaszok:


1

A futásidejű adatok kezelése során nem lehet biztonságosan értékelni kétszer a bővítéseket.

Vannak módok az újraértékelésre, de ezek megkövetelik az Ön adatainak megbízhatóságát – a szó NSA rendszertervezési értelmében: „A megbízható összetevő az, amelyik meghibásodása esetén széttörheti a rendszert”.

Lásd a BashFAQ #48 című részt a részletes vitáért. Ne feledje, hogy ha esetleg fájlneveket szeretne naplózni, akkor bármely karakter a NUL kivételével jelen lehet a UNIX fájlnévben. A $(rm -rf ~)'$(rm -rf ~)'.txt hivatalos név. A * hivatalos név.

Fontolja meg a másik megközelítést:

#!/usr/bin/env bash

trace() { echo "${FUNCNAME[1]}:${BASH_LINENO[0]}: $*" >&2; }

foo() {
        bar=baz
        trace "I just set bar to $bar"
}

foo

...amely a bash 4.4.19(1) kiadással futtatva a következőket bocsátja ki:

foo:7: I just set bar to baz

Vegye figyelembe az ${BASH_LINENO[0]} és ${FUNCNAME[1]} használatát; ennek az az oka, hogy a BASH_LINENO a következőképpen van definiálva:

Egy tömbváltozó, amelynek tagjai a sorszámok a forrásfájlokban, ahol a FUNCNAME minden megfelelő tagja meghívásra került.

Így a FUNCNAME[0] értéke trace, míg a FUNCNAME[1] értéke foo; míg a BASH_LINENO[0] az a sor, amelyből a trace meghívásra került -- egy sor, amely a foo függvényen belül van.

25.05.2018

2

Bár a eval-nek megvannak a maga veszélyei, a második bővítés az, amit:

foo(){
    local trace='$FUNCNAME $LINENO'
    local bar="something"
    eval echo "$trace: I just set bar to $bar"
}

foo

Ad:

foo 6: I just set bar to something

Csak ügyeljen arra, hogy ne eval semmi olyat, ami külső forrásból származik, mert előfordulhat, hogy parancsot injektálhat a karakterláncba.

25.05.2018
  • Nem csak a parancsbefecskendezési kockázatokat, hanem abban sem bízhat, hogy a napló pontos (és így hasznos lehet a hibakereséshez). Ha a bar='*' értéket állítja be a bar=something helyett, az idézet nem marad fenn a echo-ig, így a naplóban megjelenik a fájlnevek listája. 26.05.2018
  • Az eval 'echo '"$trace"'": I just set bar to $bar"' biztonságosabb lenne (csak a $trace kiterjesztése, és nem a karakterlánc többi része kétszer), bár nyilvánvalóan van egy könnyű használhatóság. 26.05.2018
  • @CharlesDuffy: elfogadtam. Ez a használati eset úgy tűnt, mint amire a eval eredetileg készült, és úgy éreztem, hogy valakinek meg kell mutatnia ezt megoldásként. 26.05.2018
  • sokkal rosszabb, mint "*" az ";rm -irf /" 27.05.2018
  • Azt javaslom, hogy ha valaki feltörhet dolgokat, hogy beadja ezt a parancsot, akkor nagyobb problémái vannak. 27.05.2018
  • @cdarke, ...egy naplófüggvényben? A nyomkövetési szintű naplózás lényege (gyakran), hogy megmutassa, milyen adatokkal dolgozik futás közben, és lehetővé teszi annak mérlegelését, hogyan viselkedik egy program valós körülmények között. Ezek az adatok nagyon, nagyon gyakran származnak valahonnan (feltöltött fájlnevek, más eszközökkel létrehozott fájltartalom, más folyamatok által írt naplók, amelyek az általuk behelyettesített karakterláncokat ki-tudja-honnan kapták stb.) kevésbé megbízható, mint a kódod. 27.05.2018

  • 3

    Igen a dupla bővítésre; de nem, nem azt fogja tenni, amit remél.

    Igen, a bash lehetőséget kínál a változók „kettős kiterjesztésére”, azaz egy módot arra, hogy először értelmezzünk egy változót, majd vegyük ezt egy másik változó nevének, ahol a másik változó az, ami ténylegesen bővíteni kell. Ezt "közvetettnek" hívják. Az "indirection" esetén a bash lehetővé teszi, hogy egy shell-változó hivatkozzon egy másik shell-változóra, és a végső érték a hivatkozott változóból származik. Tehát egy bash változó átadható hivatkozással.

    A szintaxis csak a normál kapcsos zárójel stíluskiterjesztés, de egy felkiáltójellel a név elé.

    ${!VARNAME}
    

    Ezt így használják:

    BAR="my final value";
    FOO=BAR
    echo ${!FOO};
    

    ...ami ezt a kimenetet állítja elő...

    my final value
    

    Nem, ezt a mechanizmust nem használhatja arra, hogy ugyanazt tegye, mint a $( eval "echo $VAR1 $VAR2" ). Az első értelmezés eredményének pontosan egy shell-változó nevének kell lennie. Nem fogad el egy karakterláncot, és nem érti a dollárjelet. Szóval ez nem fog menni:

    BAR="my final value";
    FOO='$BAR'; # The dollar sign confuses things
    echo ${!FOO}; # Fails because there is no variable named '$BAR'
    

    Tehát nem oldja meg a végső küldetést. Mindazonáltal az indirekt hatás hatékony eszköz lehet.

    25.04.2020
  • Számos előzetes SO kérdésünk van az indirekt használatával kapcsolatban -- Dinamikus változónevek a bash-ban talán a legkanonikusabb. A BashFAQ #6 egy másik nagyszerű forrás. Mindezek ellenére, ha azt hittem volna, hogy az OP itt tesz fel kérdést ebben a témában, akkor a kérdés megismétlődéseként zártam volna le, nem válaszolok rá. 25.04.2020
  • Új anyagok

    A rádiógomb ellenőrzött eseményének használata a jQueryben
    Ebben a cikkben látni fogjuk, hogyan kell dolgozni a jquery választógombbal ellenőrzött eseményeivel. A választógombok HTML gombok, amelyek segítenek kiválasztani egyetlen értéket egy csoportból...

    Körkörös függőségek megoldása terraformban adatforrásokkal – lépésről lépésre
    Mi az a körkörös függőségek Dolgozzunk egy egyszerű eseten, amikor az SQS-sor és az S3-vödör közötti körkörös függőség problémája van egy egymástól függő címkeérték miatt. provider..

    Miért érdemes elkezdeni a kódolást 2023-ban?
    01100011 01101111 01100100 01100101 — beep boop beep boop Világunk folyamatosan fejlődik a technológia körül, és naponta fejlesztenek új technológiákat a valós problémák megoldására. Amint..

    🎙 Random Noise #2  – Örökbefogadás és hit
    az analitika íratlan világának gondozása Szeretné, hogy ezek a frissítések a postaládájába kerüljenek? Iratkozzon fel itt . "Ha önvezető autókat gyártanak, akkor mi miért ne..

    A legrosszabb politika és prediktív modellek májátültetésre jelöltek számára az Egyesült Államokban
    A máj (vagy óangolul lifer) az emberi test legnehezebb belső szervére utal, amely csendesen működik a nap 24 órájában. Mit csinál a máj? 500 feladatot hajt végre a szervezet egészségének..

    5 webhely, amely 2022-ben fejleszti front-end fejlesztői készségeit
    Frontendmentor.io A tényleges projektek létrehozásával a Frontendmentor.io segítséget nyújt a front-end kódolási képességeinek fejlesztésében. A kódolást azután kezdheti meg, hogy..

    Mikor kell használni a Type-t az interfészhez képest a TypeScriptben?
    A TypeScript a JavaScript gépelt szuperkészlete, amely statikus gépelést ad a nyelvhez. Ez megkönnyíti a robusztus és karbantartható kód írását azáltal, hogy a hibákat a fordítási időben..