Làm cách nào để thay thế chỗ dành sẵn $ {} trong tệp văn bản?


163

Tôi muốn chuyển đầu ra của tệp "mẫu" sang MySQL, tệp có các biến như ${dbName}xen kẽ. Tiện ích dòng lệnh để thay thế các trường hợp này và chuyển đầu ra thành đầu ra tiêu chuẩn là gì?

Câu trả lời:


192

Trầm tích !

Đã cho template.txt:

Số này là $ {i}
Từ này là $ {word}

chúng ta chỉ cần nói:

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

Cảm ơn Jonathan Leffler về mẹo để truyền nhiều -eđối số cho cùng một sedlời mời.


13
Bạn có thể kết hợp hai lệnh sed đó thành một: sed -e "s / \ $ {i} / 1 /" -e "s / \ $ {word} / dog /"; đó là hiệu quả hơn. Bạn có thể gặp vấn đề với một số phiên bản sed ở khoảng 100 hoạt động như vậy (vấn đề từ nhiều năm trước - có thể vẫn không đúng, nhưng hãy cẩn thận với HP-UX).
Jonathan Leffler

1
Cảm ơn Jonathan, chính xác những gì tôi đang tìm kiếm.
Dana the Sane

3
Gợi ý nhỏ: nếu "1" hoặc "con chó" trong ví dụ đã cho có chứa ký hiệu đô la, bạn sẽ phải thoát nó bằng dấu gạch chéo ngược (nếu không thay thế sẽ không xảy ra).
MatthieuP

9
Bạn cũng không cần cat. Tất cả bạn cần là sed -e "s/\${i}/1/" -e "s/\${word}/dog/" template.text.
HardlyKnowEm

3
Nếu văn bản thay thế là mật khẩu thì sao? Trong trường hợp này, sedsẽ mong đợi một văn bản thoát, đó là một rắc rối.
jpbochi

177

Cập nhật

Đây là một giải pháp từ yottatsa cho một câu hỏi tương tự chỉ thay thế cho các biến như $ VAR hoặc $ {VAR}, và là một câu hỏi ngắn gọn

i=32 word=foo envsubst < template.txt

Tất nhiên nếu tôitừ trong môi trường của bạn, thì đó chỉ là

envsubst < template.txt

Trên máy Mac của tôi, có vẻ như nó đã được cài đặt như một phần của gettext và từ MacGPG2

Câu trả lời cũ

Đây là một cải tiến cho giải pháp từ mogsie cho một câu hỏi tương tự, giải pháp của tôi không yêu cầu bạn phải bỏ qua các trích dẫn kép, mogsie cũng vậy, nhưng anh ấy là một lót!

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

Sức mạnh của hai giải pháp này là bạn chỉ nhận được một vài loại mở rộng vỏ không xảy ra bình thường $ ((...)), `...` và $ (...), mặc dù dấu gạch chéo ngược một thoát ký tự ở đây, nhưng bạn không phải lo lắng rằng việc phân tích cú pháp có lỗi và nó thực hiện nhiều dòng tốt.


6
Tôi đang tìm kiếm trần envsubstkhông hoạt động nếu envars của bạn không xuất khẩu.
Toddius Zho 11/2/2015

4
@ToddiusZho: Không có biến nào giống như biến môi trường không được xuất - chính xác là xuất khẩu biến biến shell thành biến môi trường. envsubst, như tên gọi của nó, chỉ nhận ra các biến môi trường , không phải biến vỏ . Cũng đáng lưu ý rằng đó envsubstlà một tiện ích GNU và do đó không được cài đặt sẵn hoặc có sẵn trên tất cả các nền tảng.
mkuity0

2
Có thể một cách khác để nói là envsubst chỉ nhìn thấy các biến môi trường quy trình riêng của nó, vì vậy các biến shell "bình thường" mà bạn có thể đã xác định trước đó (trên các dòng riêng biệt) không được kế thừa bởi các tiến trình con trừ khi bạn "xuất" chúng. Trong việc sử dụng ví dụ của tôi về gettext trên, tôi đang thay đổi môi trường gettext thừa hưởng thông qua một cơ chế bash bằng cách đặt trước họ cho lệnh tôi sắp chạy
plockc

1
Tôi có một chuỗi có $ HOME trong đó, tôi thấy $ HOME được làm như vỏ mặc định để làm, thay vào đó $ HOME là của riêng tôi / home / zw963, nhưng, có vẻ như không hỗ trợ thay thế $ (cat / etc / hostname), vì vậy nó không hoàn thành phù hợp với nhu cầu của riêng tôi.
zw963

3
Cảm ơn "Câu trả lời cũ", vì nó không chỉ cho phép các biến, mà còn là một lệnh shell như $ (ls -l)
Alek

46

Sử dụng /bin/sh. Tạo một tập lệnh shell nhỏ đặt các biến và sau đó phân tích mẫu bằng cách sử dụng chính shell. Giống như vậy (chỉnh sửa để xử lý các dòng mới chính xác):

Tệp template.txt:

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

Tập tin 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"

Đầu ra:

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

2
Tại sao không chỉ: trong khi đọc dòng; làm tiếng vang eval "$ line"; xong <./template.txt ??? Không cần phải đọc toàn bộ tập tin vào bộ nhớ, chỉ cần nhổ nó ra từng dòng một bằng cách sử dụng nhiều đầu và đuôi. Nhưng 'eval' vẫn ổn - trừ khi mẫu có chứa các ký tự shell như dấu ngoặc kép.
Jonathan Leffler

16
Điều này rất nguy hiểm! Tất cả các bashlệnh trong đầu vào sẽ được thực hiện. Nếu mẫu là: "các từ là; rm -rf $ HOME" bạn sẽ mất các tệp.
rzymek

1
@rzymek - Hãy nhớ rằng, anh ấy muốn chuyển trực tiếp tệp này vào cơ sở dữ liệu. Vì vậy, xuất hiện, đầu vào là đáng tin cậy.
gnud

4
@gnud Có một sự khác biệt giữa tin tưởng một tệp đủ để lưu trữ nội dung của nó và tin tưởng nó đủ để thực thi bất cứ thứ gì nó chứa.
Đánh dấu

3
Để lưu ý các ràng buộc: (a) dấu ngoặc kép trong đầu vào bị loại bỏ một cách lặng lẽ, (b) readlệnh, như được viết, cắt khoảng trắng dẫn đầu và dấu cách từ mỗi dòng và \ ký tự 'ăn' ., (C) chỉ sử dụng điều này nếu bạn hoàn toàn tin tưởng hoặc kiểm soát đầu vào, bởi vì các thay thế lệnh ( `…` hoặc $(…)) được nhúng trong đầu vào cho phép thực thi các lệnh tùy ý do sử dụng eval. Cuối cùng, có một cơ hội nhỏ echosai lầm khi bắt đầu một dòng cho một trong các tùy chọn dòng lệnh của nó.
mkuity0

23

Tôi đã suy nghĩ về điều này một lần nữa, với sự quan tâm gần đây và tôi nghĩ rằng công cụ mà tôi nghĩ ban đầu là m4, bộ xử lý macro cho autotools. Vì vậy, thay vì biến tôi đã chỉ định ban đầu, bạn sẽ sử dụng:

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

1
Giải pháp này có ít nhược điểm nhất của các câu trả lời ở đây. Bạn có biết cách nào để thay thế $ {DBNAME} thay vì chỉ DBNAME không?
Jack Davidson

@JackDavidson Tôi sẽ sử dụng envsubstcho việc sử dụng thay thế / tạo khuôn mẫu đơn giản này, như đã đề cập trong các câu trả lời khác. m4là một công cụ tuyệt vời, nhưng nó là một bộ tiền xử lý đầy đủ với nhiều tính năng hơn và do đó phức tạp có thể không cần thiết nếu bạn chỉ muốn thay thế một số biến.
imiric

13

template.txt

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

dữ liệu

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

trình phân tích cú pháp

#!/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
Như đã lưu ý ở nơi khác: Chỉ sử dụng điều này nếu bạn hoàn toàn tin tưởng hoặc kiểm soát đầu vào, bởi vì các thay thế lệnh ( `…` hoặc $(…)) được nhúng trong đầu vào cho phép thực thi các lệnh tùy ý do sử dụng evalvà thực thi trực tiếp mã shell do sử dụng source. Ngoài ra, dấu ngoặc kép trong đầu vào bị loại bỏ lặng lẽ và echocó thể nhầm phần đầu của một dòng cho một trong các tùy chọn dòng lệnh của nó.
mkuity0

Thật không may, điều này loại bỏ tất cả các dấu ngoặc kép (") khỏi tệp kết quả. Có cách nào để thực hiện tương tự mà không xóa dấu ngoặc kép không?
Ivaylo Slavov

Tôi tìm thấy những gì tôi đang tìm kiếm ở đây: stackoverflow.com/a/11050943/795158 ; Tôi đã sử dụng envsubst. Sự khác biệt là các vars phải được xuất khẩu với tôi.
Ivaylo Slavov

nếu tệp văn bản chứa "` "hoặc". " , công trình sẽ thất bại.
shuiqiang

12

Đây là một chức năng Bash mạnh mẽ - mặc dù sử dụng eval- nên an toàn khi sử dụng.

Tất cả ${varName}các tham chiếu biến trong văn bản đầu vào được mở rộng dựa trên các biến của vỏ gọi.

Không có gì khác được mở rộng: không tham chiếu biến có tên không được đặt trong {...}(chẳng hạn như $varName), cũng không phải thay thế lệnh ( $(...)và cú pháp kế thừa `...`), cũng không phải thay thế số học ( $((...))và cú pháp kế thừa $[...]).

Để coi một $nghĩa đen, - hãy \xem nó; ví dụ:\${HOME}

Lưu ý rằng đầu vào chỉ được chấp nhận thông qua stdin .

Thí dụ:

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

Mã nguồn chức năng:

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
}

Chức năng giả định rằng không có 0x1, 0x2, 0x3, và 0x4ký tự điều khiển có mặt trong đầu vào, bởi vì những ký tự. được sử dụng nội bộ - vì hàm xử lý văn bản , đó phải là một giả định an toàn.


2
Đây là một trong những câu trả lời tốt nhất ở đây. Ngay cả với việc sử dụng evalnó là khá an toàn để sử dụng.
anubhava

1
Giải pháp này hoạt động với các tệp JSON! (thoát "đúng cách!)
WBAR

2
Một điều tuyệt vời với giải pháp này là nó sẽ cho phép bạn cung cấp mặc định cho các biến bị thiếu ${FOO:-bar}hoặc chỉ xuất ra thứ gì đó nếu nó được đặt - ${HOME+Home is ${HOME}}. Tôi nghi ngờ với một phần mở rộng nhỏ, nó cũng có thể trả về mã thoát cho các biến bị thiếu ${FOO?Foo is missing}nhưng hiện tại tldp.org/LDP/abs/html/parameter-substlation.html có một danh sách các biến này nếu điều đó giúp
Stuart Moore

11

Tạo rendertemplate.sh:

#!/usr/bin/env bash

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

template.tmpl:

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

Kết xuất mẫu:

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

2
Điều này loại bỏ các chuỗi trích dẫn kép
vrtx54234

Đã thử: eval "echo $ (cat $ 1)" - không trích dẫn, và nó hoạt động với tôi.
access_granted

2
Từ góc độ bảo mật, đây là tin xấu. Nếu mẫu của bạn chứa $(rm -rf ~), bạn đang chạy mã đó.
Charles Duffy

eval "echo \"$(cat $1)\"" Hoạt động tuyệt vời!
dev devv

10

Đây là giải pháp của tôi với perl dựa trên câu trả lời trước, thay thế các biến môi trường:

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

2
Điều đó thật tuyệt. Đừng bao giờ có perl, nhưng khi bạn làm, điều này đơn giản và dễ dàng.
Aaron McMillin

5

Nếu bạn cởi mở để sử dụng Perl , đó sẽ là gợi ý của tôi. Mặc dù có thể có một số chuyên gia sed và / hoặc AWK có thể biết cách làm điều này dễ dàng hơn nhiều. Nếu bạn có một ánh xạ phức tạp hơn không chỉ là dbName cho các thay thế của mình, bạn có thể mở rộng điều này khá dễ dàng, nhưng bạn cũng có thể đưa nó vào một tập lệnh Perl tiêu chuẩn vào thời điểm đó.

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

Một tập lệnh Perl ngắn để làm một cái gì đó phức tạp hơn một chút (xử lý nhiều khóa):

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

Nếu bạn đặt tên cho tập lệnh trên là tập lệnh thay thế, thì nó có thể được sử dụng như sau:

replace-script < yourfile | mysql

1
Hoạt động cho các biến đơn, nhưng làm cách nào để bao gồm 'hoặc' cho các biến khác?
Dana the Sane

2
Có nhiều cách bạn có thể làm điều này với perl, tất cả tùy thuộc vào mức độ phức tạp và / hoặc an toàn mà bạn muốn làm điều này. Các ví dụ phức tạp hơn có thể được tìm thấy ở đây: perlmonks.org/?node_id=718936
Beau Simensen

3
Sử dụng perl sạch hơn rất nhiều so với cố gắng sử dụng vỏ. Dành thời gian để thực hiện công việc này thay vì thử một số giải pháp dựa trên vỏ được đề cập khác.
jdigital

1
Gần đây đã phải giải quyết một vấn đề tương tự. Cuối cùng tôi đã đi với perl (envsubst có vẻ hứa hẹn một chút, nhưng nó quá khó để kiểm soát).
phù hợp

5

Đây là một cách để có được trình bao thay thế cho bạn, như thể nội dung của tệp được nhập giữa các dấu ngoặc kép.

Sử dụng ví dụ về template.txt với nội dung:

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

Dòng sau sẽ khiến shell nội suy nội dung của template.txt và ghi kết quả vào tiêu chuẩn.

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

Giải trình:

  • iwordđược thông qua khi các biến môi trường được chuyển sang thực thi sh.
  • sh thực hiện các nội dung của chuỗi nó được thông qua.
  • Các chuỗi được viết cạnh nhau trở thành một chuỗi, chuỗi đó là:
    • ' echo "' + " $(cat template.txt)" + ' "'
  • Vì sự thay thế là giữa ", " $(cat template.txt)" trở thành đầu ra của cat template.txt.
  • Vì vậy, lệnh được thực hiện bởi sh -ctrở thành:
    • echo "The number is ${i}\nThe word is ${word}",
    • trong đó iwordlà các biến môi trường được chỉ định.

Từ góc độ bảo mật, đây là tin xấu. Nếu mẫu của bạn chứa, giả sử, '$(rm -rf ~)'$(rm -rf ~)các trích dẫn bằng chữ trong tệp mẫu sẽ khớp với các mẫu bạn đã thêm trước khi mở rộng.
Charles Duffy

Tôi không các trích dẫn trong mẫu khớp với các trích dẫn ngoài mẫu, tôi tin rằng trình bao đang giải quyết mẫu và chuỗi trong thiết bị đầu cuối một cách độc lập (loại bỏ các trích dẫn một cách hiệu quả) sau đó nối chúng. Một phiên bản kiểm tra không xóa thư mục chính của bạn là '$(echo a)'$(echo a). Nó sản xuất 'a'a. Điều chính đang xảy ra là đầu tiên echo abên trong 'đang được đánh giá, có thể không phải là những gì bạn mong đợi kể từ khi nó xảy ra ', nhưng là hành vi tương tự như bao gồm 'trong một "chuỗi trích dẫn.
Apriori

Vì vậy, điều này không an toàn theo nghĩa là nó cho phép tác giả mẫu thực thi mã của họ. Tuy nhiên, cách báo giá được đánh giá không thực sự ảnh hưởng đến bảo mật. Mở rộng bất cứ điều gì một "chuỗi trích dẫn (bao gồm $(...)) là điểm.
Apriori

Đó có phải là điểm không? Tôi chỉ thấy họ yêu cầu ${varname}, chứ không phải mở rộng rủi ro bảo mật cao hơn.
Charles Duffy

... Điều đó nói rằng, tôi phải khác nhau (re: trong mẫu và trích dẫn ngoài mẫu có thể khớp). Khi bạn đặt một trích dẫn trong chuỗi của mình, bạn sẽ tách thành một chuỗi trích dẫn đơn echo ", theo sau là một chuỗi trích dẫn kép với các ký tự bằng chữ template.txt, theo sau là một chuỗi ký tự khác ", tất cả được nối vào một đối số duy nhất được truyền vào sh -c. Bạn đúng rằng 'không thể khớp được (vì nó được tiêu thụ bởi lớp vỏ bên ngoài thay vì được chuyển sang lớp bên trong), nhưng "chắc chắn là có thể, do đó, một mẫu chứa Gotcha"; rm -rf ~; echo "có thể được thực thi.
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
Đây không an toàn vì nó sẽ thực hiện thay thế lệnh trong mẫu nếu họ có một hàng đầu xuyệc ngược ví dụ\$(date)
Peter Dolberg

1
Ngoài điểm hợp lệ của Peter: Tôi khuyên bạn nên sử dụng while IFS= read -r line; dolàm readlệnh, nếu không, bạn sẽ loại bỏ khoảng trắng hàng đầu và dấu kiểm từ mỗi dòng đầu vào. Ngoài ra, echocó thể nhầm phần đầu của một dòng với một trong các tùy chọn dòng lệnh của nó, vì vậy tốt hơn nên sử dụng printf '%s\n'. Cuối cùng, an toàn hơn để trích dẫn kép ${1}.
mkuity0

4

Tôi sẽ đề nghị sử dụng một cái gì đó như Sigil : https://github.com/gliderlabs/sigil

Nó được biên dịch thành một nhị phân duy nhất, vì vậy nó rất dễ cài đặt trên các hệ thống.

Sau đó, bạn có thể thực hiện một lớp lót đơn giản như sau:

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

Điều này an toàn hơn nhiều evalvà dễ dàng hơn khi sử dụng regex hoặcsed


2
Câu trả lời chính xác! Đó là một hệ thống khuôn mẫu thích hợp và dễ làm việc hơn nhiều so với các câu trả lời khác.
Erfan

BTW, tốt hơn nên tránh catvà sử dụng <my-file.conf.templatethay vào đó để bạn đưa ra sigilmột tệp xử lý thực sự thay vì một bộ xếp hình.
Charles Duffy

2

Tôi tìm thấy chủ đề này trong khi tự hỏi điều tương tự. Nó truyền cảm hứng cho tôi về điều này (cẩn thận với backticks)

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

4
Một tốc ký bash cho $(cat file)$(< file)
glenn jackman

3
Rõ ràng phương pháp này gây rối với các ngắt dòng, tức là tệp của tôi đã lặp lại tất cả trong một dòng.
Arthur Corenzan

@ArthurCorenzan: Thật vậy, ngắt dòng được thay thế bằng dấu cách. Để khắc phục điều đó, bạn phải sử dụng eval echo "\"$(cat FILE)\""nhưng điều đó vẫn có thể bị thiếu trong các trích dẫn kép trong đầu vào bị loại bỏ.
mkuity0

Như đã lưu ý ở nơi khác: Chỉ sử dụng điều này nếu bạn hoàn toàn tin tưởng hoặc kiểm soát đầu vào, bởi vì các thay thế lệnh ( `…` hoặc $(…)) được nhúng trong đầu vào cho phép thực thi các lệnh tùy ý do sử dụng eval.
mkuity0

2

Có rất nhiều sự lựa chọn ở đây, nhưng tôi nghĩ rằng tôi sẽ ném tôi vào đống. Nó dựa trên perl, chỉ nhắm mục tiêu các biến có dạng $ {...}, lấy tệp để xử lý làm đối số và xuất ra tệp được chuyển đổi trên thiết bị xuất chuẩn:

use Env;
Env::import();

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

print "$text";

Tất nhiên tôi không thực sự là một người perl, vì vậy có thể dễ dàng có một lỗ hổng chết người (mặc dù làm việc cho tôi).


1
Hoạt động tốt. Bạn có thể thả Env::import();dòng - nhập khẩu được ngụ ý bởi use. Ngoài ra, tôi khuyên bạn không nên xây dựng toàn bộ đầu ra trong bộ nhớ trước: chỉ cần sử dụng print;thay vì $text .= $_;bên trong vòng lặp và thả lệnh sau vòng lặp print.
mkuity0

1

Nó có thể được thực hiện trong bash chính nó nếu bạn có quyền kiểm soát định dạng tệp cấu hình. Bạn chỉ cần nguồn (".") Tệp cấu hình chứ không phải chia nhỏ nó. Điều đó đảm bảo các biến được tạo trong ngữ cảnh của shell hiện tại (và tiếp tục tồn tại) chứ không phải là lớp con (nơi biến biến mất khi lớp vỏ con thoát ra).

$ 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

Nếu tệp cấu hình của bạn không thể là tập lệnh shell, bạn chỉ có thể 'biên dịch' nó trước khi thực hiện (quá trình biên dịch phụ thuộc vào định dạng đầu vào của bạn).

$ 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

Trong trường hợp cụ thể của bạn, bạn có thể sử dụng một cái gì đó như:

$ 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

Sau đó chuyển đầu ra của go.bash vào MySQL và voila, hy vọng bạn sẽ không phá hủy cơ sở dữ liệu của mình :-).


1
Bạn không phải xuất các biến từ tệp config.data; Chỉ cần đặt chúng là đủ. Bạn dường như cũng không đọc tệp mẫu bất cứ lúc nào. Hoặc, có lẽ, tệp mẫu đã được sửa đổi và chứa các hoạt động 'echo' ... hoặc tôi có thiếu thứ gì không?
Jonathan Leffler

1
Điểm tốt về xuất khẩu, tôi làm điều đó theo mặc định để chúng có sẵn cho các mạng con và nó không gây hại gì khi chúng chết khi đi ra ngoài. Tệp 'mẫu' là tập lệnh với các câu lệnh echo. Không cần phải giới thiệu tệp thứ ba - về cơ bản, đó là thao tác loại thư.
paxdiablo

1
"Bản thân tập lệnh với các câu lệnh echo" không phải là một mẫu: nó là một tập lệnh. Hãy suy nghĩ sự khác biệt về khả năng đọc (và khả năng duy trì) giữa <xml type = "$ TYPE"> và echo '<xml type = "' $ TYPE '">'
Pierre-Olivier Vares

1
@Pierre, không có câu lệnh echo trong tập lệnh cấu hình của tôi, chúng chỉ xuất khẩu và tôi đã chỉ ra cách bạn có thể tránh ngay cả với số lượng tiền xử lý tối thiểu. Nếu bạn đang nói về câu lệnh echo trong các tập lệnh khác của tôi (như go.bash), bạn đã hiểu nhầm về kết quả - chúng không phải là một phần của giải pháp, chúng chỉ là một cách thể hiện rằng các biến đang đặt chính xác.
paxdiablo

1
@paxdiablo: Có vẻ như bạn đã quên câu hỏi: << Tôi muốn chuyển đầu ra của tệp "mẫu" sang MySQL >>. Vì vậy, việc sử dụng một mẫu IS là câu hỏi, nó không phải là "kết thúc sai của thanh". Xuất khẩu các biến và lặp lại chúng trong kịch bản khác chỉ không trả lời câu hỏi ở tất cả
Pierre-Olivier Vares

0

Tại chỗ chỉnh sửa perl của nhiều tệp có khả năng, với các bản sao lưu.

  perl -e 's/\$\{([^}]+)\}/defined $ENV{$1} ? $ENV{$1} : ""/eg' \
    -i.orig \
    -p config/test/*
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.