การแทนที่ Bash พร้อมตัวแปรที่กำหนดจากรูปแบบ glob


10

ตัวอย่างด้านล่างอธิบายถึงปัญหา เหตุใดจึงFILENAMEพิมพ์อย่างถูกต้องเมื่อสะท้อนและรับรู้เป็นรูปแบบเมื่อใช้การทดแทน?

#!/bin/bash

FILEPATH_WITH_GLOB="/home/user/file_*"
FILENAME=$(basename "$FILEPATH_WITH_GLOB")
echo $FILENAME                #file_1234
echo ${FILENAME:1:5}          #ile_*   <---why is this not ile_1

คำตอบ:


15
FILEPATH_WITH_GLOB="/home/user/file_*"

ตอนนี้FILEPATH_WITH_GLOBมี/home/user/file_*

FILENAME=$(basename "$FILEPATH_WITH_GLOB")

FILENAMEfile_*มี

echo $FILENAME                #file_1234

$FILENAMEถูก unquoted ในบริบทรายการการขยายตัวที่ผ่านการประกอบการแยก + glob เพื่อให้ขยายไปยังรายการของไฟล์ที่ตรงกัน: รุ่นชื่อไฟล์จะดำเนินการเมื่อมีการขยายตัวพารามิเตอร์

echo ${FILENAME:1:5}          #ile_*   <---why is this not ile_1

มันยังคงเป็นการขยายพารามิเตอร์ที่ไม่มีคำอธิบายในบริบทรายการดังนั้นยังคงผ่านการแยก + glob อย่างไรก็ตามที่นี่ile_*รูปแบบไม่ตรงกับไฟล์ใด ๆ ดังนั้นจึงขยายตัวเองแทน

สิ่งที่คุณอาจต้องการคือ:

shopt -s nullglob # have globs expand to nothing when they don't match
set -- /home/user/file_* # expand that pattern into the list of matching 
                         # files in $1, $2...
for file do  # loop over them
  filename=$(basename -- "$file")
  printf '%s\n' "$filename" "${filename:1:5}"
done

หรือคุณสามารถเก็บไว้ในอาร์เรย์:

shopt -s nullglob
files=(/home/user/file_*)

$filesถ้าคุณจะดูแลเกี่ยวกับการแข่งขันครั้งแรกหรือคุณรู้ว่ามีเพียงหนึ่งในการแข่งขันแล้วคุณสามารถดูไฟล์ที่เป็น bashมีพฤติกรรมที่น่ารำคาญที่มักจะ$filesขยายออกไป${files[0]}แทนที่จะเป็นองค์ประกอบทั้งหมดของอาเรย์ (พฤติกรรมที่สืบทอดมาจากการkshแก้ไขในzsh) แต่ที่นี่นั่นจะเป็นพฤติกรรมที่ต้องการอีกครั้ง


ขอบคุณสำหรับคำอธิบาย จัดการเพื่อแก้ปัญหาด้วยFILEPATH_WITH_GLOB=`echo /home/user/file_*` หลังจากคำอธิบายของคุณ
TheMeaningfulEngineer

@ อลันนั่นเป็นวิธีที่ผิดที่จะแก้ไข คุณต้องการใช้อาร์เรย์ที่นี่ ทั้งพารามิเตอร์ตำแหน่งเช่นในตัวอย่างของฉัน ($ 1, $ 2 ... ) หรืออาร์เรย์เช่น:bash files=(/home/user/file_*)
Stéphane Chazelas

(และตัวแปรตัวพิมพ์ใหญ่ทั้งหมดควรสำรองไว้สำหรับตัวแปรสภาพแวดล้อมechoไม่ควรใช้สำหรับข้อมูลโดยพลการไม่ควรปล่อยให้ใช้ตัวแปรใน unquoted ในบริบทรายการ)
Stéphane Chazelas
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.