ในฐานะที่เป็นความคิดเห็น Goldilocks' และการอ้างอิงของมนุษยชาติอธิบาย
shiftreassigns พารามิเตอร์ตำแหน่ง ( $1, $2ฯลฯ ) เพื่อที่$1จะใช้เวลาอยู่กับค่าเก่า$2,
$2ใช้เวลากับค่าของ$3ฯลฯ*
ค่าเก่า$1จะถูกยกเลิก ( $0ไม่เปลี่ยนแปลง) เหตุผลบางประการในการทำเช่นนี้ ได้แก่ :
- มันช่วยให้คุณเข้าถึงอาร์กิวเมนต์ที่สิบ (ถ้ามี) ได้ง่ายขึ้น
$10ไม่ทำงาน - ถูกตีความว่า$1ต่อกันกับ0
(และอาจสร้างบางอย่างเช่นHello0) หลังจากอาร์กิวเมนต์สิบกลายเป็นshift $9(อย่างไรก็ตามในเชลล์ที่ทันสมัยที่สุดคุณสามารถใช้${10})
- เมื่อBash Guide for Beginnersแสดงให้เห็นแล้วก็สามารถใช้ในการวนรอบข้อโต้แย้งได้ IMNSHO นี่คือเงอะงะ;
forดีกว่ามากสำหรับสิ่งนั้น
- เช่นเดียวกับในสคริปต์ตัวอย่างของคุณมันทำให้ง่ายต่อการประมวลผลข้อโต้แย้งทั้งหมดด้วยวิธีเดียวกันยกเว้นบางอย่าง ตัวอย่างเช่นในสคริปต์ของคุณ
$1และ$2เป็นสตริงข้อความในขณะที่$3และพารามิเตอร์อื่น ๆ ทั้งหมดเป็นชื่อไฟล์
ดังนั้นนี่คือวิธีการเล่น สมมติว่าสคริปต์ของคุณถูกเรียกใช้Patryk_scriptและถูกเรียกว่าเป็น
Patryk_script USSR Russia Treaty1 Atlas2 Pravda3
สคริปต์เห็น
$1 = USSR
$2 = Russia
$3 = Treaty1
$4 = Atlas2
$5 = Pravda3
คำสั่งostr="$1"กำหนดตัวแปรเพื่อostr คำสั่งUSSRแรกshiftเปลี่ยนพารามิเตอร์ตำแหน่งดังนี้:
$1 = Russia
$2 = Treaty1
$3 = Atlas2
$4 = Pravda3
คำสั่งnstr="$1"กำหนดตัวแปรเพื่อnstr คำสั่งRussiaที่สองshiftเปลี่ยนพารามิเตอร์ตำแหน่งดังนี้:
$1 = Treaty1
$2 = Atlas2
$3 = Pravda3
และแล้วforการเปลี่ยนแปลงห่วงUSSR( $ostr) ไปRussia( $nstr) ในไฟล์Treaty1, และAtlas2Pravda3
สคริปต์มีปัญหาเล็กน้อย
สำหรับไฟล์ใน $ @; ทำ
หากสคริปต์ถูกเรียกใช้เป็น
Patryk_script สหภาพโซเวียตรัสเซีย Treaty1 "World Atlas2" Pravda3
มันเห็น
$ 1 = ล้าหลัง
$ 2 = รัสเซีย
$ 3 = Treaty1
$ 4 = World Atlas2
$ 5 = Pravda3
แต่เพราะ$@ไม่ได้ยกพื้นที่ในWorld Atlas2ไม่ได้ยกมาและforห่วงคิดว่ามันมีสี่ไฟล์: Treaty1, World, และAtlas2 Pravda3ควรจะเป็นอย่างนี้
สำหรับไฟล์ใน "$ @"; ทำ
(เพื่ออ้างอิงอักขระพิเศษใด ๆ ในอาร์กิวเมนต์) หรือเพียงแค่
สำหรับไฟล์ทำ
(ซึ่งเทียบเท่ากับเวอร์ชันที่ยาวกว่า)
eval "sed 's /" $ ostr "/" $ nstr "/ g' $ file"
ไม่จำเป็นต้องมีสิ่งนี้เพื่อให้เป็นevalและการผ่านการป้อนข้อมูลของผู้ใช้ที่ไม่ถูกตรวจสอบไปยังevalอาจเป็นอันตรายได้ ตัวอย่างเช่นหากสคริปต์ถูกเรียกเป็น
Patryk_script "'; rm *;'" สนธิสัญญารัสเซีย 1 Atlas2 Pravda3
มันจะดำเนินการrm *! นี่เป็นเรื่องที่น่ากังวลอย่างมากหากสคริปต์สามารถเรียกใช้ด้วยสิทธิ์ที่สูงกว่าของผู้ใช้ที่เรียกใช้งาน เช่นหากสามารถเรียกใช้ผ่านsudoหรือเรียกใช้จากเว็บอินเตอร์เฟส อาจไม่สำคัญหากคุณใช้เป็นตัวคุณเองในไดเรกทอรีของคุณ แต่มันสามารถเปลี่ยนเป็น
sed "s / $ ostr / $ nstr / g" "$ file"
สิ่งนี้ยังคงมีความเสี่ยงอยู่บ้าง แต่ก็มีความรุนแรงน้อยกว่ามาก
if [ -f $file ], > $file.tmpและmv $file.tmp $file
ควรจะเป็นif [ -f "$file" ], > "$file.tmp"และmv "$file.tmp" "$file"ตามลำดับในการจัดการชื่อไฟล์ที่อาจมีช่องว่าง (หรือตัวตลกและอื่น ๆ ) ในพวกเขา ( eval "sed …คำสั่งยัง mangles ชื่อไฟล์ที่มีช่องว่างอยู่ด้วย)
* shiftรับอาร์กิวเมนต์ตัวเลือก: จำนวนเต็มบวกที่ระบุจำนวนพารามิเตอร์ที่ต้องการเลื่อน ค่าเริ่มต้นคือหนึ่ง ( 1) ยกตัวอย่างเช่นshift 4เป็นสาเหตุ$5
ที่จะกลายเป็น$1,
$6ที่จะกลายเป็น$2และอื่น ๆ (โปรดทราบว่าตัวอย่างในคู่มือ Bash สำหรับผู้เริ่มต้นผิด) และเพื่อให้สคริปต์ของคุณสามารถแก้ไขได้
ostr="$1"
nstr="$2"
shift 2
ซึ่งอาจถือว่ามีความชัดเจนมากขึ้น
หมายเหตุท้าย / คำเตือน:
ภาษาพร้อมรับคำสั่งของ Windows (ไฟล์แบทช์) ยังรองรับSHIFTคำสั่งซึ่งโดยพื้นฐานแล้วเป็นสิ่งเดียวกับshiftคำสั่งใน Unix shells โดยมีความแตกต่างที่โดดเด่นหนึ่งประการซึ่งฉันจะซ่อนเพื่อพยายามป้องกันไม่ให้ผู้อื่นสับสน:
- คำสั่งเช่น
SHIFT 4นั้นเป็นข้อผิดพลาดทำให้เกิดข้อผิดพลาด“ พารามิเตอร์ไม่ถูกต้องกับคำสั่ง SHIFT”
SHIFT /nที่nเป็นจำนวนเต็มระหว่าง 0 และ 8 ที่ถูกต้อง - แต่มันไม่ได้เปลี่ยนครั้ง มันเลื่อนหนึ่งครั้งโดยเริ่มจาก อาร์กิวเมนต์ที่n ดังนั้น ทำให้(อาร์กิวเมนต์ที่ห้า) กลายเป็นและอื่น ๆ โดยปล่อยให้อาร์กิวเมนต์ 0 ถึง 3 เพียงอย่างเดียวn SHIFT /4%5%4,
%6%5
pushdและpopd)