Bash script - เนื้อหาตัวแปรเป็นคำสั่งให้เรียกใช้


159

ฉันมีสคริปต์ Perl ที่ให้หมายเลขสุ่มรายการที่กำหนดไว้ซึ่งสอดคล้องกับบรรทัดของไฟล์ sedถัดไปผมต้องการที่จะดึงสายที่มาจากไฟล์โดยใช้

#!/bin/bash
count=$(cat last_queries.txt | wc -l)
var=$(perl test.pl test2 $count)

ตัวแปรผลตอบแทนการส่งออกเช่น:var cat last_queries.txt | sed -n '12p;500p;700p'ปัญหาคือฉันไม่สามารถเรียกใช้คำสั่งสุดท้ายนี้ได้ ฉันพยายามด้วย$varแต่เอาต์พุตไม่ถูกต้อง (ถ้าฉันรันด้วยตนเองคำสั่งก็ใช้ได้ดีดังนั้นจึงไม่มีปัญหา) วิธีที่ถูกต้องในการทำเช่นนี้คืออะไร?

PS: แน่นอนว่าฉันสามารถทำงานทั้งหมดใน Perl ได้ แต่ฉันพยายามเรียนรู้ด้วยวิธีนี้เพราะมันสามารถช่วยฉันในสถานการณ์อื่นได้

คำตอบ:


215

คุณเพียงแค่ต้องทำ:

#!/bin/bash
count=$(cat last_queries.txt | wc -l)
$(perl test.pl test2 $count)

อย่างไรก็ตามหากคุณต้องการเรียกคำสั่ง Perl ของคุณในภายหลังและนั่นคือสาเหตุที่คุณต้องการกำหนดให้กับตัวแปรดังนั้น:

#!/bin/bash
count=$(cat last_queries.txt | wc -l)
var="perl test.pl test2 $count" # You need double quotes to get your $count value substituted.

...stuff...

eval $var

ตามความช่วยเหลือของ Bash:

~$ help eval
eval: eval [arg ...]
    Execute arguments as a shell command.

    Combine ARGs into a single string, use the result as input to the shell,
    and execute the resulting commands.

    Exit Status:
    Returns exit status of command or success if command is null.


2
line=$((${RANDOM} % $(wc -l < /etc/passwd)))
sed -n "${line}p" /etc/passwd

เพียงแค่มีไฟล์ของคุณแทน

ในตัวอย่างนี้ฉันใช้ไฟล์ / etc / password โดยใช้ตัวแปรพิเศษ${RANDOM}(ที่ฉันเรียนรู้ที่นี่) และsedนิพจน์ที่คุณมีความแตกต่างเพียงอย่างเดียวคือฉันใช้เครื่องหมายคำพูดคู่แทนการอนุญาตให้ขยายตัวแปร


2

ในกรณีที่คุณมีตัวแปรหลายตัวที่มีอาร์กิวเมนต์สำหรับคำสั่งที่คุณกำลังเรียกใช้ไม่ใช่แค่สายอักขระเดียวคุณไม่ควรใช้ eval โดยตรงเนื่องจากจะล้มเหลวในกรณีต่อไปนี้:

function echo_arguments() {
  echo "Argument 1: $1"
  echo "Argument 2: $2"
  echo "Argument 3: $3"
  echo "Argument 4: $4"
}

# Note we are passing 3 arguments to `echo_arguments`, not 4
eval echo_arguments arg1 arg2 "Some arg"

ผลลัพธ์:

Argument 1: arg1
Argument 2: arg2
Argument 3: Some
Argument 4: arg

โปรดทราบว่าแม้ว่า "บาง ARG" จะถูกส่งเป็นอาร์กิวเมนต์เดียวให้evalอ่านเป็นสองข้อ

คุณสามารถใช้สตริงแทนคำสั่งเอง:

# The regular bash eval works by jamming all its arguments into a string then
# evaluating the string. This function treats its arguments as individual
# arguments to be passed to the command being run.
function eval_command() {
  "$@";
}

สังเกตความแตกต่างระหว่างเอาท์พุทevalและeval_commandฟังก์ชั่นใหม่:

eval_command echo_arguments arg1 arg2 "Some arg"

ผลลัพธ์:

Argument 1: arg1
Argument 2: arg2
Argument 3: Some arg
Argument 4:

1
เพื่อหลีกเลี่ยงการประเมินผลของแต่ละองค์ประกอบหลังจากพื้นที่เช่นในตัวอย่างแรกของคุณกับ EVAL eval 'echo_arguments arg1 arg2 "Some arg"'ห่อมันด้วยคำพูดเดียว: จากนั้นเอาต์พุตจะเป็นดังตัวอย่างที่สองของคุณ
Noam Manos
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.