สมมติว่าฉันมีตัวแปรเปลือก Unix ดังต่อไปนี้
variable=abc,def,ghij
ฉันต้องการที่จะดึงค่าทั้งหมด ( abc
, def
และghij
) โดยใช้สำหรับวงและผ่านแต่ละค่าลงในขั้นตอน
$variable
สคริปต์ควรอนุญาตให้มีการแยกจำนวนข้อของค่าคั่นด้วยเครื่องหมายจุลภาคจาก
สมมติว่าฉันมีตัวแปรเปลือก Unix ดังต่อไปนี้
variable=abc,def,ghij
ฉันต้องการที่จะดึงค่าทั้งหมด ( abc
, def
และghij
) โดยใช้สำหรับวงและผ่านแต่ละค่าลงในขั้นตอน
$variable
สคริปต์ควรอนุญาตให้มีการแยกจำนวนข้อของค่าคั่นด้วยเครื่องหมายจุลภาคจาก
คำตอบ:
คุณสามารถใช้สคริปต์ต่อไปนี้เพื่อสำรวจตัวแปรของคุณแบบไดนามิกไม่ว่าจะมีกี่เขตข้อมูลตราบเท่าที่คั่นด้วยเครื่องหมายจุลภาคเท่านั้น
variable=abc,def,ghij
for i in $(echo $variable | sed "s/,/ /g")
do
# call your procedure/other scripts here below
echo "$i"
done
แทนที่จะecho "$i"
เรียกด้านบนระหว่างdo
และdone
ภายใน for loop คุณสามารถเรียกใช้ขั้นตอนของคุณproc "$i"
ได้
อัปเดต : ตัวอย่างข้อมูลด้านบนใช้งานได้หากค่าของตัวแปรไม่มีช่องว่าง หากคุณมีข้อกำหนดดังกล่าวโปรดใช้หนึ่งในวิธีแก้ปัญหาที่สามารถเปลี่ยนแปลงIFS
และแยกวิเคราะห์ตัวแปรของคุณได้
หวังว่านี่จะช่วยได้
$variable
มีช่องว่างเช่นvariable=a b,c,d
=> พิมพ์ 4 บรรทัด (a | b | c | d) แทนที่จะเป็น 3 (ab | c | d)
"value
** คุณช่วยอัปเดตได้ไหมว่ามี regex ใดที่จะลบออก ..
ไม่ยุ่งกับ IFS
ไม่เรียกคำสั่งภายนอก
variable=abc,def,ghij
for i in ${variable//,/ }
do
# call your procedure/other scripts here below
echo "$i"
done
การใช้การจัดการสตริง bash http://www.tldp.org/LDP/abs/html/string-manipulation.html
IFS
!
$i
มีช่องว่างค่าเหล่านั้นจะถูกแบ่ง (และนั่นอาจเป็นสาเหตุที่ส่งผ่านแบบคั่นด้วยจุลภาคแทนที่จะคั่นด้วยช่องว่าง)
for i in ${variable//,/$IFS} do; echo "$i"; done
หากคุณตั้งค่าตัวคั่นฟิลด์อื่นคุณสามารถใช้for
ลูปได้โดยตรง:
IFS=","
for v in $variable
do
# things with "$v" ...
done
คุณยังสามารถจัดเก็บค่าในอาร์เรย์แล้ววนซ้ำตามที่ระบุไว้ในฉันจะแยกสตริงบนตัวคั่นใน Bash ได้อย่างไร :
IFS=, read -ra values <<< "$variable"
for v in "${values[@]}"
do
# things with "$v"
done
$ variable="abc,def,ghij"
$ IFS=","
$ for v in $variable
> do
> echo "var is $v"
> done
var is abc
var is def
var is ghij
คุณสามารถค้นหาวิธีการที่กว้างขึ้นในการแก้ปัญหานี้วิธีการย้ำผ่านรายการคั่นด้วยเครื่องหมายจุลภาคและรันคำสั่งสำหรับแต่ละรายการ
ตัวอย่างแนวทางที่สอง:
$ IFS=, read -ra vals <<< "abc,def,ghij"
$ printf "%s\n" "${vals[@]}"
abc
def
ghij
$ for v in "${vals[@]}"; do echo "$v --"; done
abc --
def --
ghij --
while
เพื่ออ่านในอาร์เรย์และอีกอันหนึ่งเพื่อวนดูผลลัพธ์
IFS
กลับไปยังสิ่งที่เป็นมาก่อนหรือไม่?
#/bin/bash
TESTSTR="abc,def,ghij"
for i in $(echo $TESTSTR | tr ',' '\n')
do
echo $i
done
ฉันชอบใช้ tr แทน sed เนื่องจาก sed มีปัญหากับตัวอักษรพิเศษเช่น \ r \ n ในบางกรณี
วิธีอื่นคือการตั้งค่า IFS เป็นตัวคั่นบางตัว
นี่คือโซลูชันทางเลือกที่ใช้ tr ที่ไม่ใช้ echo ซึ่งแสดงเป็นซับเดียว
for v in $(tr ',' '\n' <<< "$var") ; do something_with "$v" ; done
รู้สึกเป็นระเบียบมากขึ้นโดยไม่มีเสียงสะท้อน แต่นั่นเป็นเพียงความชอบส่วนตัวของฉัน
ลองอันนี้.
#/bin/bash
testpid="abc,def,ghij"
count=`echo $testpid | grep -o ',' | wc -l` # this is not a good way
count=`expr $count + 1`
while [ $count -gt 0 ] ; do
echo $testpid | cut -d ',' -f $i
count=`expr $count - 1 `
done
http://stackoverflow.com/questions/8629330/unix-count-of-columns-in-file
. หลังจากนั้นให้ทำการวนซ้ำในขณะที่วนซ้ำ คุณจะได้รับสิ่งนั้น
อีกวิธีหนึ่งที่ไม่ใช้ IFS และยังคงรักษาช่องว่างไว้:
$ var="a bc,def,ghij"
$ while read line; do echo line="$line"; done < <(echo "$var" | tr ',' '\n')
line=a bc
line=def
line=ghij
นี่คือโซลูชัน bash ที่แท้จริงของฉันที่ไม่เปลี่ยน IFS และสามารถใช้ตัวคั่น regex ที่กำหนดเองได้
loop_custom_delimited() {
local list=$1
local delimiter=$2
local item
if [[ $delimiter != ' ' ]]; then
list=$(echo $list | sed 's/ /'`echo -e "\010"`'/g' | sed -E "s/$delimiter/ /g")
fi
for item in $list; do
item=$(echo $item | sed 's/'`echo -e "\010"`'/ /g')
echo "$item"
done
}