ใน bash เท่านั้นไม่มีคำสั่งภายนอก:
str="foobarbazblargblurg"
[[ $str =~ ${str//?/(.)} ]]
printf "%s%s%s%s " "${BASH_REMATCH[@]:1}"
หรือเป็นเวอร์ชันไพพ์แบบบรรทัดเดียว:
echo foobarbazblargblurg |
{ IFS= read -r str; [[ $str =~ ${str//?/(.)} ]]; \
printf "%s%s%s%s " "${BASH_REMATCH[@]:1}"; }
วิธีการทำงานนี้คือการแปลงอักขระแต่ละตัวของสตริงให้เป็น "(.)" สำหรับการจับคู่และจับภาพด้วย regex =~
จากนั้นเพียงแค่ส่งออกนิพจน์ที่จับจาก BASH_REMATCH[]
อาร์เรย์จัดกลุ่มตามที่ต้องการ ช่องว่างนำหน้า / ท้าย / กลางถูกรักษาไว้ให้ลบเครื่องหมายคำพูดรอบ ๆ"${BASH_REMATCH[@]:1}"
เพื่อละเว้น
ที่นี่มันถูกรวมไว้ในฟังก์ชั่นอันนี้จะประมวลผลข้อโต้แย้งหรืออ่าน stdin หากไม่มีข้อโต้แย้ง:
function fmt4() {
while IFS= read -r str; do
[[ $str =~ ${str//?/(.)} ]]
printf "%s%s%s%s " "${BASH_REMATCH[@]:1}"
done < <( (( $# )) && printf '%s\n' "$@" || printf '%s\n' $(< /dev/stdin) )
}
$ echo foobarbazblargblurg | fmt4
foob arba zbla rgbl urg
คุณสามารถกำหนดพารามิเตอร์จำนวนเพื่อปรับรูปแบบสตริงได้อย่างง่ายดาย
เพิ่มช่องว่างต่อท้ายใช้สองprintf
s แทนหนึ่งถ้าเป็นปัญหา:
printf "%s%s%s%s" "${BASH_REMATCH[@]:1:4}"
(( ${#BASH_REMATCH[@]} > 5 )) && printf " %s%s%s%s" "${BASH_REMATCH[@]:5}"
ครั้งแรก printf
พิมพ์ (สูงสุด) 4 ตัวอักษรตัวแรกที่สองตามเงื่อนไขพิมพ์ส่วนที่เหลือทั้งหมด (ถ้ามี) ด้วยพื้นที่ชั้นนำเพื่อแยกกลุ่ม การทดสอบมีไว้สำหรับ 5 องค์ประกอบที่ไม่ใช่ 4 เพื่ออธิบายองค์ประกอบของศูนย์
หมายเหตุ:
- เปลือก
printf
's %c
สามารถนำมาใช้แทน%s
, %c
(อาจจะ) ทำให้ความตั้งใจที่ชัดเจน แต่ก็ไม่ได้หลายไบต์ปลอดภัยของตัวละคร หากเวอร์ชันของ bash ของคุณมีความสามารถดังกล่าวข้างต้นจะปลอดภัยทุกตัวอักษรหลายไบต์
- เชลล์
printf
นำสตริงรูปแบบของมันกลับมาใช้ใหม่จนกว่ามันจะหมดข้อโต้แย้งดังนั้นมันจึงกลืนกิน 4 อาร์กิวเมนต์ในแต่ละครั้งและจัดการกับอาร์กิวเมนต์ที่ต่อท้าย (ดังนั้นไม่จำเป็นต้องใช้เคสที่มีขอบซึ่งแตกต่างจากคำตอบอื่น ๆ
BASH_REMATCH[0]
เป็นสตริงที่ตรงกันทั้งหมดดังนั้นเอาต์พุตเริ่มต้นจากดัชนี 1 เท่านั้น
- ใช้
printf -v myvar ...
แทนเพื่อจัดเก็บกับตัวแปรmyvar
(ขึ้นอยู่กับพฤติกรรมการอ่านลูป / subshell ปกติ)
- เพิ่ม
printf "\n"
ถ้าจำเป็น
คุณสามารถทำให้การทำงานข้างต้นในzsh
ถ้าคุณใช้อาร์เรย์match[]
แทนBASH_REMATCH[]
และลบ 1 จากดัชนีทั้งหมดที่zsh
ไม่ได้เก็บองค์ประกอบ 0 กับการแข่งขันทั้งหมด
sed
ฉันพยายามก่อนฉันจะเตะตัวเอง