เรียกใช้สตริงเป็นคำสั่งภายในสคริปต์ Bash


152

ฉันมีสคริปต์ Bash ที่สร้างสตริงเพื่อทำงานเป็นคำสั่ง

สคริปต์:

#! /bin/bash

matchdir="/home/joao/robocup/runner_workdir/matches/testmatch/"

teamAComm="`pwd`/a.sh"
teamBComm="`pwd`/b.sh"
include="`pwd`/server_official.conf"
serverbin='/usr/local/bin/rcssserver'

cd $matchdir
illcommando="$serverbin include='$include' server::team_l_start = '${teamAComm}' server::team_r_start = '${teamBComm}' CSVSaver::save='true' CSVSaver::filename = 'out.csv'"

echo "running: $illcommando"
# $illcommando > server-output.log 2> server-error.log
$illcommando

$serverbinซึ่งดูเหมือนจะไม่จัดหาข้อโต้แย้งได้อย่างถูกต้องไป

เอาต์พุตสคริปต์:

running: /usr/local/bin/rcssserver include='/home/joao/robocup/runner_workdir/server_official.conf' server::team_l_start = '/home/joao/robocup/runner_workdir/a.sh' server::team_r_start = '/home/joao/robocup/runner_workdir/b.sh' CSVSaver::save='true' CSVSaver::filename = 'out.csv'
rcssserver-14.0.1

Copyright (C) 1995, 1996, 1997, 1998, 1999 Electrotechnical Laboratory.
2000 - 2009 RoboCup Soccer Simulator Maintenance Group.


Usage: /usr/local/bin/rcssserver [[-[-]]namespace::option=value]
                                 [[-[-]][namespace::]help]
                                 [[-[-]]include=file]
Options:
    help
        display generic help

    include=file
        parse the specified configuration file.  Configuration files
        have the same format as the command line options. The
        configuration file specified will be parsed before all
        subsequent options.

    server::help
        display detailed help for the "server" module

    player::help
        display detailed help for the "player" module

    CSVSaver::help
        display detailed help for the "CSVSaver" module

CSVSaver Options:
    CSVSaver::save=<on|off|true|false|1|0|>
        If save is on/true, then the saver will attempt to save the
        results to the database.  Otherwise it will do nothing.

        current value: false

    CSVSaver::filename='<STRING>'
        The file to save the results to.  If this file does not
        exist it will be created.  If the file does exist, the results
        will be appended to the end.

        current value: 'out.csv'

ถ้าฉันเพียงวางคำสั่ง/usr/local/bin/rcssserver include='/home/joao/robocup/runner_workdir/server_official.conf' server::team_l_start = '/home/joao/robocup/runner_workdir/a.sh' server::team_r_start = '/home/joao/robocup/runner_workdir/b.sh' CSVSaver::save='true' CSVSaver::filename = 'out.csv'(ในผลลัพธ์หลังจาก "runnning:") มันทำงานได้ดี



ทราบว่าในบางกรณีที่คุณต้องทำ: echo | whateverCommandsแทนเพียงwhateverCommands(เช่นผมต้องทำเช่นนี้| tail -`echo | whateverCommands`)
แอนดรู

คำตอบ:


279

คุณสามารถใช้evalเพื่อรันสตริง:

eval $illcommando

2
Eval pass forward ค่าส่งคืนคำสั่ง ( ค่าส่งคืนไม่ใช่เอาต์พุตสตริง) หรือไม่?
Tomáš Zato - Reinstate Monica

3
evalเป็นคำสั่งที่ชั่วร้ายในทุกภาษาการเขียนโปรแกรมดังนั้นควรใช้ด้วยความระมัดระวัง
Krishnadas PC

1
eval "$illcommando", มีคำพูดที่จะไม่ได้คำสั่งของคุณ mangled ก่อนที่มันจะวิ่ง ลองใช้evalค่าที่illcommando='printf "%s\n" " * "'มีและไม่มีเครื่องหมายอัญประกาศเพื่อดูความแตกต่าง
ชาร์ลส์ดัฟฟี่

@ TomášZato-ReinstateMonica ใช่มันจะส่งต่อค่าส่งคืนของคำสั่ง อย่างไรก็ตามมันไม่ได้ตั้งค่า"${PIPESTATUS[@]}"ตัวแปรในการทุบตีอย่างถูกต้อง อย่างไรก็ตามset -o pipefailทำให้evalส่งคืนรหัสการออกจากความล้มเหลวได้อย่างถูกต้องหากคำสั่งมีคำสั่งที่ล้มเหลวในการไพพ์ไปยังคำสั่งที่สำเร็จ
Cameron Hudson

ฉันพยายามทำบางอย่างเช่นgrep -E '$filter' unfiltered.txt > filtered.txtฉันไม่มีเงื่อนงำว่าทำไมมันถึงทำงานในบรรทัดคำสั่งและทำไมค่าที่คำนวณได้มันไม่ทำงานใน bash script คำตอบของคุณบันทึกสคริปต์ของฉัน ฉันจะเพิ่มที่นี่ยังมีตัวอย่างเอกสารที่ดีที่ฉันได้ใช้เพื่อให้เข้าใจถึงวิธีการทำงานของ eval linuxhint.com/bash_eval_command
student0495

28

ฉันมักจะวางคำสั่งในวงเล็บ$(commandStr)ถ้าไม่ช่วยฉันหาโหมดดีบัก bash ที่ยอดเยี่ยมให้รันสคริปต์เป็นbash -x script


4
ฉันไม่แน่ใจว่า commandStr หมายถึงอะไร แต่อย่างน้อยนี่ไม่ได้ผลสำหรับฉัน จะดีกว่าถ้าคุณใช้ตัวอย่างการทำงานที่สมบูรณ์
Robin Manoli

@ RobinManoli ปรับปรุงความคมชัดของ ya
แอนดรู


10

อย่าวางคำสั่งของคุณในตัวแปรเพียงแค่เรียกใช้

matchdir="/home/joao/robocup/runner_workdir/matches/testmatch/"
PWD=$(pwd)
teamAComm="$PWD/a.sh"
teamBComm="$PWD/b.sh"
include="$PWD/server_official.conf"
serverbin='/usr/local/bin/rcssserver'    
cd $matchdir
$serverbin include=$include server::team_l_start = ${teamAComm} server::team_r_start=${teamBComm} CSVSaver::save='true' CSVSaver::filename = 'out.csv'

1
ทำแค่นั้น "${arg}"แต่ที่ผมมีตัวแปรที่ควรจะไปเพียงแค่เป็นอาร์กิวเมนต์เดียวที่ฉันได้ ตัวอย่าง: server :: team_l_start = "$ {teamAComm}"
João Portela

1

./me ปลดเปลื้อง ra_dead ()

ฉันกำลังมองหาบางอย่างเช่นนี้ แต่ฉันยังจำเป็นต้องใช้สตริงเดียวกันซ้ำลบสองพารามิเตอร์ดังนั้นฉันจึงลงเอยด้วยสิ่งที่คล้ายกัน:

my_exe ()
{
    mysql -sN -e "select $1 from heat.stack where heat.stack.name=\"$2\";"
}

นี่คือสิ่งที่ฉันใช้ในการตรวจสอบการสร้างสแต็คความร้อน openstack ในกรณีนี้ฉันคาดว่าจะมีสองเงื่อนไขการกระทำ 'CREATE' และสถานะ 'COMPLETE' บนสแต็กชื่อ "Somestack"

เพื่อให้ได้ตัวแปรเหล่านั้นฉันสามารถทำสิ่งต่อไปนี้

ACTION=$(my_exe action Somestack)
STATUS=$(my_exe status Somestack)
if [[ "$ACTION" == "CREATE" ]] && [[ "$STATUS" == "COMPLETE" ]]
...

0

นี่คือสคริปต์ build gradle ของฉันที่เรียกใช้สตริงที่เก็บในheredocs :

current_directory=$( realpath "." )
GENERATED=${current_directory}/"GENERATED"
build_gradle=$( realpath build.gradle )

## touch because .gitignore ignores this folder:
touch $GENERATED

COPY_BUILD_FILE=$( cat <<COPY_BUILD_FILE_HEREDOC

    cp 
        $build_gradle 
        $GENERATED/build.gradle

COPY_BUILD_FILE_HEREDOC
)
$COPY_BUILD_FILE

GRADLE_COMMAND=$( cat <<GRADLE_COMMAND_HEREDOC

    gradle run

        --build-file       
            $GENERATED/build.gradle

        --gradle-user-home 
            $GENERATED  

        --no-daemon

GRADLE_COMMAND_HEREDOC
)
$GRADLE_COMMAND

โลน ")" นั้นช่างน่าเกลียด แต่ฉันไม่มีเงื่อนงำว่าจะแก้ไขด้านการสังเคราะห์นั้นได้อย่างไร


0

หากต้องการดูคำสั่งทั้งหมดที่สคริปต์ดำเนินการให้เพิ่มการ-xตั้งค่าสถานะในบรรทัด shabang ของคุณและดำเนินการคำสั่งตามปกติ:

#! /bin/bash -x

matchdir="/home/joao/robocup/runner_workdir/matches/testmatch/"

teamAComm="`pwd`/a.sh"
teamBComm="`pwd`/b.sh"
include="`pwd`/server_official.conf"
serverbin='/usr/local/bin/rcssserver'

cd $matchdir
$serverbin include="$include" server::team_l_start="${teamAComm}" server::team_r_start="${teamBComm}" CSVSaver::save='true' CSVSaver::filename='out.csv'

จากนั้นหากคุณต้องการละเว้นผลลัพธ์การดีบักให้เปลี่ยนเส้นทางที่stderrอื่น

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.