'\ n' ใน `IFS = $ '\ n' เป็นตัวแปรหรือไม่


12

ฉันสังเกตเห็นว่าการกำหนด newline IFSควรมี $ เป็นคำนำหน้า

IFS=$'\n'

แต่ถ้าตั้งลำไส้ใหญ่เพียง

IFS=:

คือ\nเป็นตัวแปรหรือไม่?

คำตอบ:


21

ว่า$'...'ในbashไม่พารามิเตอร์การขยายตัวก็เป็นชนิดพิเศษนำโดยอ้างksh93ว่าการขยายตัวของผู้ที่\n, \x0a, \12รหัสตัวอักษรขึ้นบรรทัดใหม่ นอกจากนี้ยังเพิ่มzsh และยังมีในขณะที่มี นอกจากนี้ยังสนับสนุนรูปแบบเช่น\u000aksh93bash\cjzsh\C-Jksh93\x{a}

$เป็นคิวที่มันเป็นรูปแบบบางส่วนหรือการขยายตัว แต่ในกรณีใด ๆ มันแตกต่างจากรูปแบบอื่น ๆ ของการขยายการใช้งาน$(เช่น$((1 + 1)), $paramหรือ$(cmd)) ในการที่จะไม่ได้ดำเนินการให้อยู่ในเครื่องหมายหรือนี่เอกสาร ( echo "$'x'"เอาท์พุท$'x'ในเปลือกหอยทั้งหมดก็คือไม่ได้ระบุต่อ POSIX) และการขยายตัวของมันไม่ได้อยู่ภายใต้การแยก + glob แน่นอนว่ามันใกล้กับโอเปอร์เรเตอร์ของ quoting มากกว่าโอเปอเรเตอร์การขยาย

IFS=\nจะตั้งไอเอฟเอไปn( \จะถือว่าเป็นผู้ประกอบการอ้าง) และIFS="\n"หรือจะตั้งไอเอฟเอไปที่ตัวละครสองตัวทับขวาและIFS='\n'n

คุณยังสามารถใช้:

IFS='
'

หรือ

IFS="
"

หรือ

IFS=$'
'

ผ่านการขึ้นบรรทัดใหม่ที่แท้จริง แต่ที่ชัดเจนน้อยกว่า (และเป็นหนึ่งในไม่สามารถดูอื่น ๆ กว่าการใช้สิ่งที่ต้องการset listในviไม่ว่าจะ$IFSมีตัวละครอื่น ๆ ในระยะห่างรหัสที่)

IFS=:, IFS=':', IFS=":", IFS=$':'ทุกชุด IFS ไป:จึงไม่ได้เรื่องที่คุณใช้

$'...'ได้รับการสนับสนุน (ด้วยรูปแบบ) อย่างน้อย: ksh93, zsh, bash, mksh, busybox sh, shFreeBSD ksh93และbashยังมี$"..."รูปแบบของคำพูดที่ใช้สำหรับการแปลข้อความแม้ว่ามันจะไม่ค่อยได้ใช้เพราะมันยุ่งยากในการปรับใช้และใช้งานได้แบบพกพาและเชื่อถือได้

esและfishหอยยังสามารถใช้\nนอกของคำพูดที่จะขยายไปขึ้นบรรทัดใหม่

เครื่องมือบางอย่างเช่นprintfการใช้งานบางอย่างของechoหรือawkยังสามารถขยายได้\nด้วยตนเอง ตัวอย่างเช่นหนึ่งสามารถทำได้:

printf '\n'
awk 'BEGIN{printf "\n"}'
echo
echo '\n\c' # UNIX compliant echos only

ไปที่เอาต์พุตของอักขระบรรทัดใหม่ แต่โปรดทราบว่า:

IFS = $ (printf '\ n')

จะไม่ทำงานเนื่องจากการทดแทนคำสั่ง ( $(...)) ตัดอักขระบรรทัดใหม่ที่ต่อท้ายทั้งหมด อย่างไรก็ตามคุณสามารถใช้:

eval "$(printf 'IFS="\n"')"

ซึ่งใช้งานได้เนื่องจากผลลัพธ์ของการprintfสิ้นสุดใน"อักขระไม่ใช่บรรทัดใหม่

ตอนนี้เพื่อความสมบูรณ์ในrcเชลล์และอนุพันธ์ (เช่นesหรือakanga) $'\n'นั้นเป็นการขยายตัวของ\nตัวแปรนั้น(ตัวแปรที่มีชื่อคือลำดับของอักขระสองตัว\และn) เปลือกหอยเหล่านั้นไม่ได้มีข้อ จำกัด '...'ในสิ่งที่ตัวละครชื่อตัวแปรอาจจะมีและมีเพียงหนึ่งในประเภทของคำพูด:

$ rc
; '\n' = (foo bar)
; echo $'\n'
foo bar
; echo $'\n'(1)
foo

rcตัวแปรยังถูกส่งออกไปยังสภาพแวดล้อมทั้งหมด แต่อย่างน้อยในตัวแปร Unix rcสำหรับชื่อตัวแปรเช่น\nเวอร์ชันตัวแปรสภาพแวดล้อมผ่านการเข้ารหัส:

; env | grep foo | sed -n l
__5cn=foo\001bar$

( 0x5cเป็นค่าไบต์ของ ASCII \ดูด้วยว่าตัวแปรอาร์เรย์นั้นถูกเข้ารหัสด้วย 0x1 ไบต์เป็นตัวคั่น)


1
+1สำหรับระดับความรู้ปกติของมนุษย์
Steven Penny

10

นี่คือการอ้างอิง ANSI-C :

คำของแบบฟอร์ม$'string'ได้รับการปฏิบัติเป็นพิเศษ คำขยายออกไปstringโดยมีอักขระเครื่องหมายทับขวาทับกลับแทนที่ตามที่ระบุโดยมาตรฐาน ANSI C

ดังนั้น$'\n'จะถูกแทนที่ด้วยขึ้นบรรทัดใหม่

นี่คือที่ไม่เกี่ยวข้องกับเปลือกขยายตัวพารามิเตอร์$แม้จะมีการใช้งานของ


6

สตริงดังกล่าว$'\n'ได้รับการแนะนำโดยksh93และไม่ได้เป็นส่วนหนึ่งของมาตรฐาน POSIX

พวกเขาอนุญาตให้มีการใช้มากที่สุด C หนีเหมือนกันเช่นและหนีออกที่ได้รับการสนับสนุนโดย$'\u2345'echo

โปรดทราบว่าหากคุณไม่ชอบ (ในกรณีของ ksh93 หรือ bash) เพื่อใช้วิธีการหลบหนีคุณยังอาจใช้:

IFS='
'

ซึ่งเทียบเท่า แต่อ่านยากกว่า

BTW: ส่วนขยายนี้ผ่านการรับรองมาตรฐาน POSIX แล้ว แต่มีกำหนดสำหรับSUSv8ที่คาดว่าจะไม่ปรากฏก่อนปี 2020 เนื่องจากเราจำเป็นต้องทำงานในความล่าช้าของเราที่อยู่เบื้องหลังรายการข้อผิดพลาดในปัจจุบัน


ขยายแตกต่างจากที่$'...' พวกเขากำลังมากขึ้นเช่นคนสำหรับอาร์กิวเมนต์รูปแบบของecho printfสำหรับecho, 0 ต้องการใน\0123ขณะที่สำหรับ$'...'และprintfฟอร์แมต, \0123จะขึ้น\012บรรทัดใหม่ตามด้วยครอก 3
Stéphane Chazelas

1
โปรดทราบว่า$'...'ข้อมูลจำเพาะยังคงถูกกล่าวถึง ยังมีอีกหลายประเด็นที่จะต้องแก้ไขด้วยถ้อยคำที่เสนอในปัจจุบัน
Stéphane Chazelas

IIRC มันถูกปิด แต่ได้ถูกเปิดใหม่ เนื่องจากความจริงที่ว่ายังมีเวลาอีกมากก่อนที่มันจะมีประสิทธิภาพฉันจึงไม่เห็นปัญหาที่แท้จริง
schily

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