Jak zamienić symbole zastępcze $ {} w pliku tekstowym?


163

Chcę przesłać dane wyjściowe pliku „szablonu” do MySQL, plik zawierający zmienne, takie jak ${dbName}przeplatane. Jakie narzędzie wiersza poleceń zastępuje te wystąpienia i zrzuca dane wyjściowe na standardowe wyjście?

Odpowiedzi:


192

Sed !

Podany plik template.txt:

Numer to $ {i}
Słowo to $ {word}

musimy tylko powiedzieć:

sed -e "s/\${i}/1/" -e "s/\${word}/dog/" template.txt

Podziękowania dla Jonathana Lefflera za wskazówkę dotyczącą przekazywania wielu -eargumentów do tego samego sedwywołania.


13
Możesz połączyć te dwa polecenia seda w jedno: sed -e "s / \ $ {i} / 1 /" -e "s / \ $ {słowo} / dog /"; to jest bardziej wydajne. Możesz napotkać problemy z niektórymi wersjami seda przy około 100 takich operacjach (problem sprzed lat - może nadal nie jest prawdą, ale uwaga na HP-UX).
Jonathan Leffler

1
Dzięki Jonathan, dokładnie to, czego szukałem.
Dana the Sane

3
Mała wskazówka: jeśli „1” lub „pies” w podanym przykładzie zawierałby symbol dolara, należałoby go poprzedzić odwrotnym ukośnikiem (w przeciwnym razie zamiana nie nastąpi).
MatthieuP

9
Nie potrzebujesz też cat. Wszystko czego potrzebujesz to sed -e "s/\${i}/1/" -e "s/\${word}/dog/" template.text.
HardlyKnowEm

3
A jeśli tekst zastępczy to hasło? W takim przypadku sedoczekuje tekstu ucieczki, co jest kłopotliwe.
jpbochi

177

Aktualizacja

Oto rozwiązanie od yottatsy na podobne pytanie, które zastępuje tylko zmienne, takie jak $ VAR lub $ {VAR}, i jest krótkim, jednowierszowym

i=32 word=foo envsubst < template.txt

Oczywiście, jeśli ja i słowo są w twoim środowisku, to jest po prostu

envsubst < template.txt

Na moim Macu wygląda na to, że został zainstalowany jako część gettext i z MacGPG2

Stara odpowiedź

Oto ulepszenie rozwiązania z mogsie na podobne pytanie, moje rozwiązanie nie wymaga eskalowania podwójnych cudzysłowów, tak jak mogsie, ale jego jest jeden liniowiec!

eval "cat <<EOF
$(<template.txt)
EOF
" 2> /dev/null

Moc na tych dwóch rozwiązań jest to, że można dostać tylko kilka rodzajów rozszerzeń powłoki, które nie występują normalnie $ ((...)), `...` i $ (...), choć backslash jest tutaj znak ucieczki, ale nie musisz się martwić, że parsowanie ma błąd, a wiele linii jest w porządku.


6
Odkryłem, że gołe envsubstnie działa, jeśli twoje envars nie są eksportowane.
Toddius Zho

4
@ToddiusZho: Nie ma czegoś takiego jak zmienna środowiskowa, która nie jest eksportowana - to właśnie eksportowanie sprawia, że zmienna powłoki jest zmienną środowiskową. envsubstjak sama nazwa wskazuje, rozpoznaje tylko zmienne środowiskowe , a nie zmienne powłoki . Warto również zauważyć, że envsubstjest to narzędzie GNU , a zatem nie jest preinstalowane ani dostępne na wszystkich platformach.
mklement0

2
Być może można inaczej powiedzieć, że envsubst widzi tylko własne zmienne środowiskowe procesu, więc „normalne” zmienne powłoki, które mogłeś wcześniej zdefiniować (w osobnych wierszach), nie są dziedziczone przez procesy potomne, chyba że je „wyeksportujesz”. W moim przykładzie użycia gettext powyżej, modyfikuję odziedziczone środowisko gettext za pomocą mechanizmu bash, poprzedzając je przed poleceniem, które mam zamiar uruchomić
plockc

1
Mam jeden ciąg z $ HOME w nim, stwierdziłem, że $ HOME działa jako domyślna powłoka, zamiast $ HOME jako moja własna / home / zw963, ale wygląda na to, że nie obsługuje podstawiania $ (cat / etc / hostname), więc nie jest w pełni zgodny z moim własnym żądaniem.
zw963

3
Dzięki za "starą odpowiedź", ponieważ nie tylko dopuszcza zmienne, ale także polecenia powłoki, takie jak $ (ls -l)
Alek

46

Posługiwać się /bin/sh . Utwórz mały skrypt powłoki, który ustawia zmienne, a następnie przeanalizuj szablon przy użyciu samej powłoki. Tak (edytuj, aby poprawnie obsługiwać znaki nowej linii):

Plik template.txt:

the number is ${i}
the word is ${word}

Plik script.sh:

#!/bin/sh

#Set variables
i=1
word="dog"

#Read in template one line at the time, and replace variables (more
#natural (and efficient) way, thanks to Jonathan Leffler).
while read line
do
    eval echo "$line"
done < "./template.txt"

Wynik:

#sh script.sh
the number is 1
the word is dog

2
Dlaczego nie tylko: podczas czytania linii; zrobić eval echo "$ line"; gotowe <./template.txt ??? Nie ma potrzeby wczytywania całego pliku do pamięci, tylko po to, aby wypluwać go po jednej linii na raz poprzez intensywne użycie głowy i ogona. Ale 'eval' jest OK - chyba że szablon zawiera znaki powłoki, takie jak cudzysłowy.
Jonathan Leffler

16
To jest bardzo niebezpieczne! Wszystkie bashpolecenia wprowadzone na wejściu zostaną wykonane. Jeśli szablon to: "the words is; rm -rf $ HOME" stracisz pliki.
rzymek

1
@rzymek - pamiętaj, że chce on przepuścić ten plik bezpośrednio do bazy danych. Najwyraźniej dane wejściowe są zaufane.
gnud

4
@gnud Istnieje różnica między zaufaniem do pliku na tyle, aby mógł przechowywać jego zawartość, a zaufaniem mu na tyle, aby wykonać wszystko, co zawiera.
Mark

3
Aby zwrócić uwagę na ograniczenia: (a) podwójne cudzysłowy na wejściu są po cichu odrzucane, (b) readpolecenie, jak napisano, przycina początkowe i końcowe białe spacje z każdej linii i ` \ ` zjada '' znaki., (C) użyj tego tylko wtedy, gdy w pełni ufają lub kontrolują dane wejściowe, ponieważ podstawienia komend ( `…` lub $(…)) osadzone w danych wejściowych pozwalają na wykonywanie dowolnych poleceń z powodu użycia eval. Wreszcie, istnieje niewielka szansa, że echopoczątek wiersza pomylisz z jedną z opcji wiersza poleceń.
mklement0

23

Myślałem o tym ponownie, biorąc pod uwagę niedawne zainteresowanie i myślę, że narzędziem, o którym pierwotnie myślałem, był m4procesor makr dla automatycznych narzędzi. Więc zamiast zmiennej, którą pierwotnie określiłem, użyjesz:

$echo 'I am a DBNAME' | m4 -DDBNAME="database name"

1
To rozwiązanie ma najmniej wad odpowiedzi tutaj. Czy znasz jednak sposób na zastąpienie $ {DBNAME} zamiast tylko DBNAME?
Jack Davidson

@JackDavidson użyłbym envsubstdo tego prostego użycia zastępowania zmiennych / szablonów, jak wspomniano w innych odpowiedziach. m4to świetne narzędzie, ale jest to pełnowartościowy preprocesor z dużo większą liczbą funkcji, a tym samym złożonością, która może nie być potrzebna, jeśli chcesz po prostu zastąpić niektóre zmienne.
imiric

13

template.txt

Variable 1 value: ${var1}
Variable 2 value: ${var2}

data.sh

#!/usr/bin/env bash
declare var1="value 1"
declare var2="value 2"

parser.sh

#!/usr/bin/env bash

# args
declare file_data=$1
declare file_input=$2
declare file_output=$3

source $file_data
eval "echo \"$(< $file_input)\"" > $file_output

./parser.sh data.sh template.txt parsed_file.txt

parsed_file.txt

Variable 1 value: value 1
Variable 2 value: value 2

1
Jak zauważono w innym miejscu: używaj tego tylko wtedy, gdy w pełni ufasz lub kontrolujesz dane wejściowe, ponieważ podstawienia poleceń ( `…` lub $(…)) osadzone w danych wejściowych pozwalają na wykonywanie dowolnych poleceń w wyniku użycia evali bezpośrednie wykonanie kodu powłoki w wyniku użycia source. Ponadto podwójne cudzysłowy w danych wejściowych są po cichu odrzucane i echomogą pomylić początek wiersza z jedną z opcji wiersza poleceń.
mklement0

Niestety, powoduje to usunięcie wszystkich podwójnych cudzysłowów (") z pliku wynikowego. Czy istnieje sposób na zrobienie tego samego bez usuwania podwójnych cudzysłowów?
Ivaylo Slavov

Znalazłem to, czego szukałem tutaj: stackoverflow.com/a/11050943/795158 ; Użyłem envsubst. Różnica polega na tym, że vars trzeba wyeksportować, co mi odpowiadało.
Ivaylo Slavov

jeśli plik tekstowy zawiera „„ ”lub„. ” podstudnienie nie powiedzie się.
shuiqiang

12

Oto solidna funkcja Bash, która - pomimo użycia eval- powinna być bezpieczna w użyciu.

Wszystkie ${varName}odwołania do zmiennych w tekście wejściowym są interpretowane na podstawie zmiennych wywołującej powłoki.

Nic innego nie jest rozwijane: ani odwołania do zmiennych, których nazwy nie są zawarte w {...}(takie jak $varName), ani podstawienia poleceń ( $(...)i starsza składnia `...`), ani podstawienia arytmetyczne ( $((...))i starsza składnia$[...] ).

Aby traktować a $jako dosłowne, \-urzuć go; na przykład:\${HOME}

Należy pamiętać, że dane wejściowe są akceptowane tylko przez stdin .

Przykład:

$ expandVarsStrict <<<'$HOME is "${HOME}"; `date` and \$(ls)' # only ${HOME} is expanded
$HOME is "/Users/jdoe"; `date` and $(ls)

Kod źródłowy funkcji:

expandVarsStrict(){
  local line lineEscaped
  while IFS= read -r line || [[ -n $line ]]; do  # the `||` clause ensures that the last line is read even if it doesn't end with \n
    # Escape ALL chars. that could trigger an expansion..
    IFS= read -r -d '' lineEscaped < <(printf %s "$line" | tr '`([$' '\1\2\3\4')
    # ... then selectively reenable ${ references
    lineEscaped=${lineEscaped//$'\4'{/\${}
    # Finally, escape embedded double quotes to preserve them.
    lineEscaped=${lineEscaped//\"/\\\"}
    eval "printf '%s\n' \"$lineEscaped\"" | tr '\1\2\3\4' '`([$'
  done
}

Funkcja zakłada, że żadna 0x1, 0x2, 0x3, i 0x4znaki kontrolne są obecne w danych wejściowych, ponieważ te znaki. są używane wewnętrznie - ponieważ funkcja przetwarza tekst , powinno to być bezpieczne założenie.


2
To jedna z najlepszych odpowiedzi. Nawet przy użyciu evaljest całkiem bezpieczny w użyciu.
anubhava,

1
To rozwiązanie działa z plikami JSON! (uciekając "poprawnie!)
WBAR

2
Fajną rzeczą w tym rozwiązaniu jest to, że pozwoli ci podać domyślne wartości dla brakujących zmiennych ${FOO:-bar}lub wyprowadzić coś tylko wtedy, gdy jest ustawione - ${HOME+Home is ${HOME}}. Podejrzewam, że z małym rozszerzeniem może również zwracać kody wyjścia dla brakujących zmiennych, ${FOO?Foo is missing}ale obecnie tldp.org/LDP/abs/html/parameter-substitution.html ma ich listę, jeśli to pomoże
Stuart Moore

11

Utwórz rendertemplate.sh:

#!/usr/bin/env bash

eval "echo \"$(cat $1)\""

Oraz template.tmpl:

Hello, ${WORLD}
Goodbye, ${CHEESE}

Renderuj szablon:

$ export WORLD=Foo
$ CHEESE=Bar ./rendertemplate.sh template.tmpl 
Hello, Foo
Goodbye, Bar

2
To usuwa ciągi w podwójnych cudzysłowach
vrtx54234

Próbowałem: eval "echo $ (cat $ 1)" - bez cytatów i zadziałało dla mnie.
access_granted

2
Z punktu widzenia bezpieczeństwa to zła wiadomość. Jeśli Twój szablon zawiera $(rm -rf ~), uruchamiasz to jako kod.
Charles Duffy

eval "echo \"$(cat $1)\"" Działa świetnie !
dev devv

10

oto moje rozwiązanie z perlem na podstawie poprzedniej odpowiedzi, zastępuje zmienne środowiskowe:

perl -p -e 's/\$\{(\w+)\}/(exists $ENV{$1}?$ENV{$1}:"missing variable $1")/eg' < infile > outfile

2
To jest świetne. Nie zawsze masz Perla, ale kiedy już to robisz, jest to proste i proste.
Aaron McMillin

5

Jeśli jesteś otwarty na używanie Perla , to byłaby moja sugestia. Chociaż prawdopodobnie są niektórzy eksperci sed i / lub AWK, którzy prawdopodobnie wiedzą, jak to zrobić znacznie łatwiej. Jeśli masz bardziej złożone mapowanie z więcej niż tylko dbName dla swoich zamienników, możesz to dość łatwo rozszerzyć, ale równie dobrze możesz równie dobrze umieścić je w standardowym skrypcie Perla w tym momencie.

perl -p -e 's/\$\{dbName\}/testdb/s' yourfile | mysql

Krótki skrypt Perla, który robi coś bardziej skomplikowanego (obsługuje wiele kluczy):

#!/usr/bin/env perl
my %replace = ( 'dbName' => 'testdb', 'somethingElse' => 'fooBar' );
undef $/;
my $buf = <STDIN>;
$buf =~ s/\$\{$_\}/$replace{$_}/g for keys %replace;
print $buf;

Jeśli nazwiesz powyższy skrypt jako skrypt zastępujący, można go następnie użyć w następujący sposób:

replace-script < yourfile | mysql

1
Działa dla pojedynczych zmiennych, ale jak dodać „lub” dla innych?
Dana the Sane

2
Jest wiele sposobów, aby to zrobić za pomocą perla, a wszystkie zależą od tego, jak skomplikowane i / lub bezpieczne chcesz to zrobić. Bardziej skomplikowane przykłady można znaleźć tutaj: perlmonks.org/?node_id=718936
Beau Simensen

3
Używanie perla jest o wiele czystsze niż próba użycia powłoki. Poświęć trochę czasu, aby to zadziałało, zamiast wypróbować niektóre z innych wymienionych rozwiązań opartych na powłoce.
jdigital

1
Niedawno miałem do czynienia z podobnym problemem. Ostatecznie zdecydowałem się na perl (envsubst wyglądał trochę obiecująco, ale było zbyt trudne do kontrolowania).
sfitts

5

Oto sposób, aby powłoka wykonała podstawienie za Ciebie, tak jakby zawartość pliku była zamiast tego wpisywana w cudzysłowy.

Na przykładzie template.txt z zawartością:

The number is ${i}
The word is ${word}

Następujący wiersz spowoduje, że powłoka interpoluje zawartość pliku template.txt i zapisuje wynik do standardowego wyjścia.

i='1' word='dog' sh -c 'echo "'"$(cat template.txt)"'"'

Wyjaśnienie:

  • ii wordsą przekazywane jako zmienne środowiskowe ograniczone do wykonania sh.
  • sh wykonuje zawartość przekazanego ciągu.
  • Ciągi napisane obok siebie stają się jednym ciągiem, ten ciąg to:
    • ' echo "' + " $(cat template.txt)" + ' "'
  • Ponieważ podstawienie jest pomiędzy ", " $(cat template.txt)" staje się wynikiemcat template.txt .
  • Zatem polecenie wykonywane przez sh -cstaje się:
    • echo "The number is ${i}\nThe word is ${word}",
    • gdzie ii wordsą określonymi zmiennymi środowiskowymi.

Z punktu widzenia bezpieczeństwa to zła wiadomość. Jeśli twój szablon zawiera, powiedzmy, '$(rm -rf ~)'$(rm -rf ~)dosłowne cudzysłowy w pliku szablonu będą pasowały do ​​tych, które dodałeś przed jego rozwinięciem.
Charles Duffy

Nie, czy cudzysłowy w szablonie nie pasują do cytatów poza szablonem, uważam, że powłoka samodzielnie rozwiązuje szablon i ciąg w terminalu (skuteczne usuwanie cudzysłowów), a następnie je łączy. Wersja testu, która nie usuwa twojego katalogu domowego, to '$(echo a)'$(echo a). Produkuje 'a'a. Najważniejsze, co się dzieje, jest to, że pierwszy element echo awewnątrz elementu 'jest oceniany, co może nie być tym, czego się spodziewasz, ponieważ jest w nim ', ale zachowuje się tak samo, jak 'w przypadku umieszczania w "cudzysłowie.
Apriori

Nie jest to więc bezpieczne w tym sensie, że umożliwia autorowi szablonu wykonanie kodu. Jednak to, jak wyceny są oceniane, tak naprawdę nie wpływa na bezpieczeństwo. "Chodzi o rozwinięcie czegokolwiek w cudzysłowie (włącznie $(...)).
Apriori

Czy o to chodzi? Widzę tylko, że proszą o ${varname}inne rozszerzenia o wyższym ryzyku bezpieczeństwa, a nie inne rozszerzenia.
Charles Duffy

... to powiedziawszy, muszę się różnić (re: cytaty w szablonie i poza szablonem mogą być dopasowane). Kiedy umieścisz pojedynczy cudzysłów w swoim ciągu, dzielisz się na ciąg znaków z pojedynczym cudzysłowem echo ", po którym następuje podwójny cudzysłów z ciągiem literału template.txt, po którym następuje kolejny ciąg literału ", a wszystko to jest połączone w pojedynczy argument przekazywany do sh -c. Masz rację, że 'nie można dopasować (ponieważ został zużyty przez zewnętrzną powłokę, a nie przekazany do wewnętrznej), ale z "pewnością może, więc szablon zawierający Gotcha"; rm -rf ~; echo "może zostać wykonany.
Charles Duffy

4

file.tpl:

The following bash function should only replace ${var1} syntax and ignore 
other shell special chars such as `backticks` or $var2 or "double quotes". 
If I have missed anything - let me know.

script.sh:

template(){
    # usage: template file.tpl
    while read -r line ; do
            line=${line//\"/\\\"}
            line=${line//\`/\\\`}
            line=${line//\$/\\\$}
            line=${line//\\\${/\${}
            eval "echo \"$line\""; 
    done < ${1}
}

var1="*replaced*"
var2="*not replaced*"

template file.tpl > result.txt

2
To nie jest bezpieczne, ponieważ spowoduje wykonanie podstawień poleceń w szablonie, jeśli mają one wiodący ukośnik odwrotny, np.\$(date)
Peter Dolberg

1
Oprócz ważnej uwagi Petera: sugeruję użycie while IFS= read -r line; dojako readpolecenia, w przeciwnym razie usuniesz początkowe i końcowe spacje z każdego wiersza wprowadzania. Ponadto echomoże pomylić początek wiersza z jedną z opcji wiersza poleceń, więc lepiej jest użyć printf '%s\n'. Wreszcie, bezpieczniej jest podwójne cytowanie ${1}.
mklement0

4

Sugerowałbym użycie czegoś takiego jak Sigil : https://github.com/gliderlabs/sigil

Jest skompilowany do pojedynczego pliku binarnego, więc jest niezwykle łatwy do zainstalowania w systemach.

Następnie możesz wykonać prostą jedną linijkę, taką jak następujące:

cat my-file.conf.template | sigil -p $(env) > my-file.conf

Jest to znacznie bezpieczniejsze evali łatwiejsze niż użycie wyrażenia regularnego lubsed


2
Świetna odpowiedź! To właściwy system szablonów i dużo łatwiejszy w obsłudze niż inne odpowiedzi.
Erfan

BTW, lepiej unikać cati używać <my-file.conf.templatezamiast tego, aby dać sigilprawdziwy uchwyt pliku zamiast FIFO.
Charles Duffy

2

Znalazłem ten wątek, zastanawiając się nad tym samym. Zainspirowało mnie to do tego (uważaj na lewe napisy)

$ echo $MYTEST
pass!
$ cat FILE
hello $MYTEST world
$ eval echo `cat FILE`
hello pass! world

4
$(cat file)$(< file)
Bash

3
Najwyraźniej ta metoda zepsuła podziały wierszy, tzn. Mój plik został powtórzony w jednym wierszu.
Arthur Corenzan,

@ArthurCorenzan: Rzeczywiście, podziały wierszy są zastępowane spacjami. Aby to naprawić, musiałbyś użyć, eval echo "\"$(cat FILE)\""ale może to nadal być niewystarczające, ponieważ podwójne cudzysłowy w danych wejściowych są odrzucane.
mklement0

Jak zauważono w innym miejscu: używaj tego tylko wtedy, gdy w pełni ufasz lub kontrolujesz dane wejściowe, ponieważ podstawienia poleceń ( `…` lub $(…)) wbudowane w dane wejściowe pozwalają na wykonywanie dowolnych poleceń z powodu użycia eval.
mklement0

2

Sporo możliwości wyboru, ale pomyślałem, że rzucę swój na stos. Jest oparty na perlu, celuje tylko w zmienne w postaci $ {...}, pobiera plik do przetworzenia jako argument i wyprowadza przekonwertowany plik na standardowe wyjście:

use Env;
Env::import();

while(<>) { $_ =~ s/(\${\w+})/$1/eeg; $text .= $_; }

print "$text";

Oczywiście nie jestem osobą perlową, więc łatwo może być fatalna wada (chociaż dla mnie działa).


1
Działa w porządku. Możesz porzucić tę Env::import();linię - import jest implikowany przez use. Sugeruję również, aby najpierw nie gromadzić całego wyjścia w pamięci: po prostu użyj print;zamiast $text .= $_;wewnątrz pętli i porzuć printpolecenie pętli .
mklement0

1

Można to zrobić w samym bashu, jeśli masz kontrolę nad formatem pliku konfiguracyjnego. Musisz tylko pozyskać („.”) Plik konfiguracyjny, a nie podpowłokę. Zapewnia to, że zmienne są tworzone w kontekście bieżącej powłoki (i nadal istnieją), a nie w podpowłoce (gdzie zmienna znika po zamknięciu podpowłoki).

$ cat config.data
    export parm_jdbc=jdbc:db2://box7.co.uk:5000/INSTA
    export parm_user=pax
    export parm_pwd=never_you_mind

$ cat go.bash
    . config.data
    echo "JDBC string is " $parm_jdbc
    echo "Username is    " $parm_user
    echo "Password is    " $parm_pwd

$ bash go.bash
    JDBC string is  jdbc:db2://box7.co.uk:5000/INSTA
    Username is     pax
    Password is     never_you_mind

Jeśli twój plik konfiguracyjny nie może być skryptem powłoki, możesz go po prostu „skompilować” przed wykonaniem (kompilacja zależy od formatu wejściowego).

$ cat config.data
    parm_jdbc=jdbc:db2://box7.co.uk:5000/INSTA # JDBC URL
    parm_user=pax                              # user name
    parm_pwd=never_you_mind                    # password

$ cat go.bash
    cat config.data
        | sed 's/#.*$//'
        | sed 's/[ \t]*$//'
        | sed 's/^[ \t]*//'
        | grep -v '^$'
        | sed 's/^/export '
        >config.data-compiled
    . config.data-compiled
    echo "JDBC string is " $parm_jdbc
    echo "Username is    " $parm_user
    echo "Password is    " $parm_pwd

$ bash go.bash
    JDBC string is  jdbc:db2://box7.co.uk:5000/INSTA
    Username is     pax
    Password is     never_you_mind

W swoim konkretnym przypadku możesz użyć czegoś takiego:

$ cat config.data
    export p_p1=val1
    export p_p2=val2
$ cat go.bash
    . ./config.data
    echo "select * from dbtable where p1 = '$p_p1' and p2 like '$p_p2%' order by p1"
$ bash go.bash
    select * from dbtable where p1 = 'val1' and p2 like 'val2%' order by p1

Następnie prześlij wyjście go.bash do MySQL i voila, miejmy nadzieję, że nie zniszczysz swojej bazy danych :-).


1
Nie musisz eksportować zmiennych z pliku config.data; wystarczy je po prostu ustawić. Wydaje się, że w żadnym momencie nie czytasz pliku szablonu. A może plik szablonu jest zmodyfikowany i zawiera operacje „echo” ... czy czegoś mi brakuje?
Jonathan Leffler

1
Dobra uwaga na temat eksportu, robię to domyślnie, aby były dostępne dla podpowłok i nie powodują żadnych szkód, ponieważ umierają po wyjściu. Plik „szablonu” to sam skrypt z instrukcjami echo. Nie ma potrzeby wprowadzania trzeciego pliku - jest to w zasadzie operacja typu mailmerge.
paxdiablo

1
„Sam skrypt ze swoimi instrukcjami echo” nie jest szablonem: to jest skrypt. Pomyśl o różnicy w czytelności (i łatwości utrzymania) między <xml type = "$ TYPE"> a echo '<xml type = "' $ TYPE '">'
Pierre-Olivier Vares

1
@Pierre, w moim skrypcie konfiguracyjnym nie ma instrukcji echo, są one tylko eksportami i pokazałem, jak można tego uniknąć przy minimalnej ilości przetwarzania wstępnego. Jeśli mówisz o instrukcji echo w moich innych skryptach (np. go.bash), Masz niewłaściwy koniec patyka - nie są one częścią rozwiązania, są tylko sposobem pokazania, że ​​zmienne są ustawione prawidłowo.
paxdiablo

1
@paxdiablo: Wygląda na to, że zapomniałeś o pytaniu: << Chcę przesłać dane wyjściowe pliku „szablonu” do MySQL >>. Tak więc użycie szablonu JEST pytaniem, a nie „niewłaściwym końcem kija”. Eksportowanie zmienne i powtarzając je w innym scenariuszu po prostu nie odpowiedzieć na pytanie, na wszystkich
Pierre-Olivier Vares

0

Edycja na miejscu w perlu potencjalnie wielu plików z kopiami zapasowymi.

  perl -e 's/\$\{([^}]+)\}/defined $ENV{$1} ? $ENV{$1} : ""/eg' \
    -i.orig \
    -p config/test/*

0

Będziesz chciał czegoś solidniejszego niż obecne sugestie, ponieważ chociaż działają one w twoim (na razie) ograniczonym przypadku użycia, nie wystarczą w bardziej złożonych sytuacjach.

Potrzebujesz lepszego renderera. Potrzebujesz najlepszego renderera. Potrzebujesz Renderest!

Podany plik template.txt:

Cześć osobo}}!

Biegać:

$ person = Bob ./render template.txt

Zobaczysz wynik

Cześć Bob!

Zapisz go do pliku, przekierowując standardowe wyjście do pliku:

$ person = Bob ./render template.txt> rendering.txt

A jeśli zdarzy ci się renderować skrypt zawierający zmienne $ {}, których nie chcesz interpolować, The Renderest zapewni Ci ochronę bez konieczności robienia czegokolwiek innego!

Kontynuuj i zdobądź swoją kopię na https://github.com/relaxdiego/renderest

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.