การส่งตัวแปรไปยังสคริปต์ทุบตีเมื่อทำการจัดหา


18

สมมติว่าฉันมีใน main.sh:

$NAME="a string"
if [ -f $HOME/install.sh ]
    . $HOME/install.sh $NAME
fi

และใน install.sh:

echo $1

นี่ควรจะเป็นเสียงสะท้อน"a string"แต่มันก็ไม่สะท้อนอะไรเลย ทำไม?


2
โปรดอย่าอัปเดตคำถาม ด้วยวิธีนี้เราไม่สามารถเห็นสิ่งผิดปกติกับคำถามเริ่มต้นของคุณ ฉันแค่ย้อนกลับ
Valentin Bajrami

คำตอบ:


20

Michael Mrozekครอบคลุมปัญหาส่วนใหญ่และการแก้ไขของเขาจะทำงานได้เนื่องจากคุณใช้ Bash

คุณอาจสนใจในความจริงที่ว่าความสามารถในการแหล่งสคริปต์ด้วยอาร์กิวเมนต์เป็น bashism ในshหรือdashคุณmain.shจะไม่ได้สะท้อนอะไรเลยเพราะข้อโต้แย้งไปยังสคริปต์ที่มาจะถูกละเว้นและ$1จะอ้างถึงการโต้แย้งmain.sh.

เมื่อคุณแหล่งสคริปต์ในshมันเป็นเหมือนคุณเพียงคัดลอกและวางข้อความของสคริปต์ที่มาลงในไฟล์ที่มันมา ลองพิจารณาสิ่งต่อไปนี้ (โปรดทราบว่าฉันได้ทำการแก้ไขที่ Michael แนะนำ):

$ bash ./test.sh
A String
$ sh ./test.sh

$ sh ./test.sh "HELLO WORLD"
HELLO WORLD

"ใน sh หรือ dash main.sh ของคุณจะไม่ได้สะท้อนอะไรเลยเพราะข้อโต้แย้งไปยังสคริปต์ที่มาจะถูกละเว้นและ $ 1 จะอ้างถึงการโต้แย้งไปยัง main.sh" นั่นคือสิ่งที่เกิดขึ้น ขอบคุณสำหรับคำตอบ.
ใครบางคนยังคงใช้ MS-DOS ของคุณ

ฉันทำเครื่องหมายว่าคุณตอบว่าได้รับการยอมรับเนื่องจากปัญหาจริงไม่ได้มีข้อผิดพลาดในสคริปต์ของฉัน แต่ส่วนใหญ่เป็นเพราะฉันบรรจุ sh ด้วย bash และทุบตีทำงานเลียนแบบ sh ในสถานการณ์นี้ คำตอบของคุณทำให้ฉันสูงขึ้นเกี่ยวกับปัญหานี้ขอบคุณ
ใครบางคนยังคงใช้ MS-DOS ของคุณ

2
ในทางเทคนิคแล้วมันเป็น kshism ที่นี่ (มีอยู่แล้วใน ksh86 น่าจะเร็วกว่านี้) @ Somebodystilluses คุณ -DOS ข้อกำหนด "sh" ไม่ได้บอกว่าจะเกิดอะไรขึ้นถ้าคุณส่งอาร์กิวเมนต์พิเศษดังนั้นพฤติกรรมของเส้นประหรือการทุบตีจะไม่ "sh" เกินกว่าตัวอื่น ๆ และใช้ได้อย่างเท่าเทียมกัน
Stéphane Chazelas

16

ฉันเห็นข้อผิดพลาดสามข้อ:

  1. สายงานของคุณผิด:

    $NAME="a string"

    เมื่อคุณกำหนดให้กับตัวแปรคุณจะไม่รวม$; มันควรจะเป็น:

    NAME="a string"
  2. คุณกำลังขาดหายไปthen; บรรทัดเงื่อนไขควรเป็น:

    if [ -f $HOME/install.sh ]; then
  3. คุณไม่ได้อ้าง$NAMEถึงแม้ว่าจะมีช่องว่าง บรรทัดซอร์สควรเป็น:

    . $HOME/install.sh "$NAME"

เขามีข้อผิดพลาดอื่น ๆ อีกสองสามข้อ แต่ฉันไม่คิดว่าจะต้องเป็นแหล่งที่มาของปัญหาที่เกิดขึ้น
Steven D

@ สตีเว่นคุณพูดถูกมีอีกสองสามอย่างที่ฉันไม่ได้พูดถึง มันใช้งานได้สำหรับฉันด้วยการแก้ไขที่ฉันได้ระบุไว้ในตอนนี้
Michael Mrozek

@Steven เมื่อฉันถูกขว้างปาด้วยกันสคริปต์ที่จะลองผมย่อมัน[ -f $HOME/install.sh ] && . $HOME/install.sh $NAME; ฉันไม่ควรทำสิ่งเช่นนั้นเมื่อฉันมองหาข้อผิดพลาด
Michael Mrozek

ดูเหมือนว่าปัญหาอื่น ๆ ที่ฉันคิดว่าอยู่ที่นั่นจริง ๆ แล้วไม่มีปัญหาเนื่องจากเขากล่าวถึงทุบตีโดยเฉพาะ
Steven D

5

เพียงตั้งค่าพารามิเตอร์ของคุณก่อนที่จะจัดหาสคริปต์!

main.sh

#!/bin/bash
NAME=${*:-"a string"}
if [[ -f install.sh ]];
then
    set -- $NAME ;
    . install.sh ;
fi
exit;

install.sh

#!/bin/bash
echo  " i am sourced by [ ${0##*/} ]";
echo  " with [ $@ ] as parametr(s) ";
exit;

ทดสอบ

u@h$ ./main.sh some args
 i am sourced by [ main.sh ]
 with [ some args ] as parametr(s) 
u@h$

คุณจะตั้งค่าสถานะได้อย่างไร
Jonathan Landrum

แก้ไข: คุณเห็นได้ชัดเพียงสตริงพวกเขาหลังจากที่--เช่นเดียวกับพวกเขาเป็นข้อโต้แย้งคำสั่ง:set -- -v foo -l bar -j "${bin}"
โจนาธานแลนดรัม
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.