Запустити рядок як команду в 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`)
Andrew

Відповіді:


279

Ви можете використовувати evalдля виконання рядка:

eval $illcommando

2
Чи передає eval вперед значення повернення команди ( значення повернення , а не рядок)?
Томаш Зато - Відновити Моніку

3
evalце зла команда у всіх мовах програмування, тому використовуйте її з обережністю.
ПК

1
eval "$illcommando", з цитатами , щоб ваша команда не була налаштована до запуску. Спробуйте evalзі значенням illcommando='printf "%s\n" " * "'з і без лапок, щоб побачити різницю.
Чарльз Даффі

@ TomášZato-ReinstateMonica Так, він передає зворотне значення команди. Однак він НЕ встановлює "${PIPESTATUS[@]}"змінну в bash належним чином. Однак set -o pipefailправильно викликає evalповернення коду виходу з ладу, якщо команда містить невдалу команду, передану в успішну команду.
Камерон Хадсон

Я намагався зробити щось на кшталт grep -E '$filter' unfiltered.txt > filtered.txt, я не мав поняття, чому він працює в командному рядку і чому з обчисленими значеннями він не працює в bash script. Ваша відповідь зберегла мій сценарій. Я додам сюди також кілька приємних задокументованих прикладів, які я використав, щоб краще зрозуміти, як працює eval. linuxhint.com/bash_eval_command
student0495

28

Зазвичай я розміщую команди в круглих дужках $(commandStr), якщо це не допомагає, я знаходжу великий режим налагодження bash, запустіть сценарій якbash -x script


4
Я не впевнений, на що посилається commandStr, але принаймні це не спрацювало для мене. Краще, якщо ви використовуєте повні робочі приклади.
Робін Манолі

@RobinManoli Покращив ясність для вас.
Андрій


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}"
Жоао Портела

1

./me кидає pozovi_dead ()

Я шукав щось подібне, але мені також потрібно було повторно використовувати той самий рядок мінус два параметри, щоб я закінчив щось подібне:

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

Це те, що я використовую для моніторингу створення тепловитрати opentack. У цьому випадку я очікую двох умов, дії "СТВОРИТИ" та статусу "ЗАВЕРШИТИ" на стеці під назвою "Somestack"

Щоб отримати ці змінні, я можу зробити щось на кшталт:

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

0

Ось мій сценарій збірки gradle, який виконує рядки, збережені в гередоках :

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прапор до рядка шабанга та виконайте команду зазвичай:

#! /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кудись переспрямуйте .

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.