سؤال

أرغب في توجيه إخراج ملف "القالب" إلى MySQL، حيث يحتوي الملف على متغيرات مثل ${dbName} تتخللها.ما هي الأداة المساعدة لسطر الأوامر لاستبدال هذه الحالات وتفريغ الإخراج إلى الإخراج القياسي؟

هل كانت مفيدة؟

المحلول

سد !

ونظرا template.txt:

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

وعلينا فقط أن أقول:

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

وبفضل جوناثان ليفلر للمعلومات لتمرير الحجج -e متعددة لنفس الاحتجاج sed.

نصائح أخرى

تحديث

وهنا هو الحل من yottatsa على سؤال مماثل أن يفعل استبدال فقط للمتغيرات مثل $ VAR أو $ {VAR }، وهي قصيرة أونيلينير

i=32 word=foo envsubst < template.txt

وبالطبع إذا <م> <ط / م> و <م> كلمة هي في البيئة الخاصة بك، ثم انها مجرد

envsubst < template.txt

في بلدي ماك يبدو تم تثبيته كجزء من gettext ومن MacGPG2

قديم الإجابة

وهنا تحسنا في حل من mogsie على سؤال مماثل، يا الحل لا تتطلب منك ESCALE مزدوج ونقلت وmogsie في ذلك، ولكن له هو بطانة واحد!

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

والقوة على هذين الحلين هو أن تحصل فقط على أنواع قليلة من التوسعات قذيفة التي لا تحدث عادة $ ((...))، `` ...، و$ (...)، على الرغم من مائل <م> هو حرف هروب هنا، ولكن لم يكن لديك ما يدعو للقلق أن إعراب له علة، وأنه لا خطوط متعددة على ما يرام.

استخدم /bin/sh. إنشاء شيل الصغيرة التي تحدد المتغيرات، ومن ثم تحليل القالب باستخدام قذيفة نفسها. مثل ذلك (تحرير لمعالجة أسطر جديدة بشكل صحيح):

template.txt الملف:

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

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"

إخراج:

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

وكنت أفكر في هذا مرة أخرى، نظرا للاهتمام الأخيرة، وأعتقد أن الأداة التي كنت أفكر في الأصل من كان <لأ href = "http://www.gnu.org/software/m4/manual/index أتش تي أم أل "يختلط =" noreferrer "> m4 أو المعالج الكلي للautotools. وذلك بدلا من المتغير I المحدد أصلا، وكنت استخدام:

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

و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

وهنا قال لي حل مع بيرل على أساس الإجابة السابقة، يستبدل متغيرات البيئة:

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

وهنا أ وظيفة باش قوية ذلك - على الرغم من استخدام eval - يجب أن تكون آمنة للاستخدام.

الجميع ${varName} يتم توسيع المراجع المتغيرة في نص الإدخال بناءً على متغيرات shell المستدعية.

لا شيء آخر تم توسيعه:لا المراجع المتغيرة التي أسمائها لا المغلقة في {...} (مثل $varName)، ولا بدائل الأوامر ($(...) وبناء الجملة التراثية `...`)، ولا البدائل الحسابية ($((...)) وبناء الجملة التراثية $[...]).

لعلاج أ $ كحرفٍ، \- الهروب منه؛على سبيل المثال:\${HOME}

لاحظ أنه يتم قبول الإدخال فقط عبر com.stdin.

مثال:

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

كود مصدر الوظيفة:

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
}

تفترض الدالة أن لا 0x1, 0x2, 0x3, ، و 0x4 أحرف التحكم موجودة في الإدخال، لأن تلك الأحرف.يتم استخدامها داخليًا - منذ العمليات الوظيفية نص, ، يجب أن يكون هذا افتراضًا آمنًا.

إذا كنت مفتوحة لاستخدام بيرل ، من شأنه أن يكون اقتراحي. على الرغم من أن هناك ربما بعض ااا و / أو <وأ href = "HTTP: // داخلي. wikipedia.org/wiki/AWK "يختلط =" نوفولو noreferrer "> AWK الخبراء انه من المحتمل ان تعرف كيف تفعل هذا أسهل بكثير. إذا كان لديك تعيين أكثر تعقيدا مع أكثر من مجرد DBNAME لاستبدال الخاصة بك هل يمكن تمديد هذا بسهولة جدا، ولكن قد وضعت للتو، وكذلك قبل أن تتحول إلى النصي بيرل قياسي عند تلك النقطة.

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

وهناك سيناريو بيرل قصيرة أن تفعل شيئا قليلا أكثر تعقيدا (التعامل مع مفاتيح متعددة):

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

إذا قمت بتسمية النصي أعلاه كما استبدال النصي، فإنه يمكن أن تستخدم بعد ذلك كما يلي:

replace-script < yourfile | mysql

إنشاء rendertemplate.sh:

#!/usr/bin/env bash

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

وtemplate.tmpl:

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

وعرض النموذج:

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

و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

وأود أن أقترح استخدام شيء من هذا القبيل على سيجيل : ل      https://github.com/gliderlabs/sigil

ويتم تصنيف أن ثنائي واحد، لذلك فمن السهل للغاية لتثبيت على أنظمة.

وبعد ذلك يمكنك القيام بسيطة أونيلينير كما يلي:

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

وهذا هو أكثر أمانا من eval وأسهل ثم استخدام التعابير المنطقية أو sed

ولقد وجدت هذا الموضوع في حين يتساءل نفس الشيء. من وحي لي لهذا (الحذر مع backticks)

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

والكثير من الخيارات هنا، ولكن أحسب أن كنت إرم الألغام على الكومة. ومن بيرل القائمة، ويستهدف فقط متغيرات النموذج $ {...}، ويأخذ الملف لمعالجة كحجة و إخراج الملف المحول على المعياري:

use Env;
Env::import();

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

print "$text";

وبطبيعة الحال أنا لا حقا شخص بيرل، لذلك يمكن أن يكون هناك بسهولة الخلل القاتل (يعمل بالنسبة لي على الرغم من).

ويمكن ان يتم ذلك في سحق نفسه إذا كان لديك السيطرة على شكل ملف التكوين. تحتاج فقط إلى المصدر ( ".") ملف التكوين بدلا من المستوى الفرعي ذلك. يضمن يتم إنشاء المتغيرات في سياق قذيفة الحالية (وتستمر في الوجود) بدلا من المستوى الفرعي (حيث المتغير تختفي عندما يتم إنهاء المستوى الفرعي).

$ 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

إذا ملف التكوين الخاص بك لا يمكن أن يكون شيل، يمكنك فقط "تجميع" من قبل تنفيذ هكذا (تجميع يعتمد على شكل المدخلات الخاصة بك).

$ 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

في حالة معينة، هل يمكن استخدام شيء من هذا القبيل:

$ 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

وبعد ذلك أنبوب إخراج go.bash إلى الخلية وفويلا، ونأمل أن لن يدمر قاعدة البيانات الخاصة بك: -)

فيما يلي طريقة لجعل الصدفة تقوم بالاستبدال نيابةً عنك، كما لو تم كتابة محتويات الملف بين علامتي اقتباس مزدوجتين.

باستخدام مثال template.txt مع المحتويات:

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

سيؤدي السطر التالي إلى قيام الصدفة باستيفاء محتويات template.txt وكتابة النتيجة إلى الوضع القياسي.

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

توضيح:

  • i و word يتم تمريرها كمتغيرات البيئة التي تم تحديدها لتنفيذ sh.
  • sh ينفذ محتويات السلسلة التي تم تمريرها.
  • السلاسل المكتوبة بجانب بعضها البعض تصبح سلسلة واحدة، تلك السلسلة هي:
    • 'echo "' + "$(cat template.txt)" + '"'
  • وبما أن الاستبدال يقع بين ", "$(cat template.txt)" يصبح إخراج cat template.txt.
  • لذلك تم تنفيذ الأمر بواسطة sh -c يصبح:
    • echo "The number is ${i}\nThe word is ${word}",
    • أين i و word هي متغيرات البيئة المحددة.
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top