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?
bash
command-line
text-processing
templating
Dana the Sane
źródło
źródło
cat
. Wszystko czego potrzebujesz tosed -e "s/\${i}/1/" -e "s/\${word}/dog/" template.text
.sed
oczekuje tekstu ucieczki, co jest kłopotliwe.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
Oczywiście, jeśli ja i słowo są w twoim środowisku, to jest po prostu
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!
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.
źródło
envsubst
nie działa, jeśli twoje envars nie są eksportowane.envsubst
jak sama nazwa wskazuje, rozpoznaje tylko zmienne środowiskowe , a nie zmienne powłoki . Warto również zauważyć, żeenvsubst
jest to narzędzie GNU , a zatem nie jest preinstalowane ani dostępne na wszystkich platformach.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:
Plik script.sh:
Wynik:
źródło
bash
polecenia wprowadzone na wejściu zostaną wykonane. Jeśli szablon to: "the words is; rm -rf $ HOME" stracisz pliki.read
polecenie, 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życiaeval
. Wreszcie, istnieje niewielka szansa, żeecho
początek wiersza pomylisz z jedną z opcji wiersza poleceń.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ł
m4
procesor makr dla automatycznych narzędzi. Więc zamiast zmiennej, którą pierwotnie określiłem, użyjesz:źródło
envsubst
do tego prostego użycia zastępowania zmiennych / szablonów, jak wspomniano w innych odpowiedziach.m4
to ś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.template.txt
data.sh
parser.sh
parsed_file.txt
źródło
`…`
lub$(…)
) osadzone w danych wejściowych pozwalają na wykonywanie dowolnych poleceń w wyniku użyciaeval
i bezpośrednie wykonanie kodu powłoki w wyniku użyciasource
. Ponadto podwójne cudzysłowy w danych wejściowych są po cichu odrzucane iecho
mogą pomylić początek wiersza z jedną z opcji wiersza poleceń.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:
Kod źródłowy funkcji:
Funkcja zakłada, że żadna
0x1
,0x2
,0x3
, i0x4
znaki 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.źródło
eval
jest całkiem bezpieczny w użyciu."
poprawnie!)${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żeUtwórz
rendertemplate.sh
:Oraz
template.tmpl
:Renderuj szablon:
źródło
$(rm -rf ~)
, uruchamiasz to jako kod.eval "echo \"$(cat $1)\""
Działa świetnie !oto moje rozwiązanie z perlem na podstawie poprzedniej odpowiedzi, zastępuje zmienne środowiskowe:
źródło
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.
Krótki skrypt Perla, który robi coś bardziej skomplikowanego (obsługuje wiele kluczy):
Jeśli nazwiesz powyższy skrypt jako skrypt zastępujący, można go następnie użyć w następujący sposób:
źródło
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ą:
Następujący wiersz spowoduje, że powłoka interpoluje zawartość pliku template.txt i zapisuje wynik do standardowego wyjścia.
Wyjaśnienie:
i
iword
są przekazywane jako zmienne środowiskowe ograniczone do wykonaniash
.sh
wykonuje zawartość przekazanego ciągu.echo "
' + "$(cat template.txt)
" + '"
'"
, "$(cat template.txt)
" staje się wynikiemcat template.txt
.sh -c
staje się:echo "The number is ${i}\nThe word is ${word}"
,i
iword
są określonymi zmiennymi środowiskowymi.źródło
'$(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.'$(echo a)'$(echo a)
. Produkuje'a'a
. Najważniejsze, co się dzieje, jest to, że pierwszy elementecho a
wewną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."
Chodzi o rozwinięcie czegokolwiek w cudzysłowie (włącznie$(...)
).${varname}
inne rozszerzenia o wyższym ryzyku bezpieczeństwa, a nie inne rozszerzenia.echo "
, po którym następuje podwójny cudzysłów z ciągiem literałutemplate.txt
, po którym następuje kolejny ciąg literału"
, a wszystko to jest połączone w pojedynczy argument przekazywany dosh -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ącyGotcha"; rm -rf ~; echo "
może zostać wykonany.file.tpl:
script.sh:
źródło
\$(date)
while IFS= read -r line; do
jakoread
polecenia, w przeciwnym razie usuniesz początkowe i końcowe spacje z każdego wiersza wprowadzania. Ponadtoecho
moż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}
.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:
Jest to znacznie bezpieczniejsze
eval
i łatwiejsze niż użycie wyrażenia regularnego lubsed
źródło
cat
i używać<my-file.conf.template
zamiast tego, aby daćsigil
prawdziwy uchwyt pliku zamiast FIFO.Znalazłem ten wątek, zastanawiając się nad tym samym. Zainspirowało mnie to do tego (uważaj na lewe napisy)
źródło
$(cat file)
$(< file)
eval echo "\"$(cat FILE)\""
ale może to nadal być niewystarczające, ponieważ podwójne cudzysłowy w danych wejściowych są odrzucane.`…`
lub$(…)
) wbudowane w dane wejściowe pozwalają na wykonywanie dowolnych poleceń z powodu użyciaeval
.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:
Oczywiście nie jestem osobą perlową, więc łatwo może być fatalna wada (chociaż dla mnie działa).
źródło
Env::import();
linię - import jest implikowany przezuse
. Sugeruję również, aby najpierw nie gromadzić całego wyjścia w pamięci: po prostu użyjprint;
zamiast$text .= $_;
wewnątrz pętli i porzućprint
polecenie pętli .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).
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).
W swoim konkretnym przypadku możesz użyć czegoś takiego:
Następnie prześlij wyjście go.bash do MySQL i voila, miejmy nadzieję, że nie zniszczysz swojej bazy danych :-).
źródło
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.Edycja na miejscu w perlu potencjalnie wielu plików z kopiami zapasowymi.
źródło
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
źródło