ต้องมีเงื่อนไขอะไรบ้างสำหรับไฟล์ที่จะเป็นไฟล์ข้อความตามที่กำหนดโดย POSIX


22

POSIX กำหนดไฟล์ข้อความเป็น:

ไฟล์ที่มีตัวอักษรจัดเป็นศูนย์หรือมากกว่าบรรทัด บรรทัดไม่มีอักขระ NUL และไม่มีความยาวเกิน {LINE_MAX} ไบต์รวมถึงอักขระ <newline> แม้ว่า POSIX.1-2017 จะไม่แยกความแตกต่างระหว่างไฟล์ข้อความและไฟล์ไบนารี (ดูมาตรฐาน ISO C) แต่ยูทิลิตี้จำนวนมากจะสร้างเอาต์พุตที่สามารถคาดการณ์ได้หรือมีความหมายเมื่อทำงานกับไฟล์ข้อความ ยูทิลิตี้มาตรฐานที่มีข้อ จำกัด ดังกล่าวจะระบุ "ไฟล์ข้อความ" ในส่วน STDIN หรือ INPUT FILES เสมอ

ที่มา: http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_403

อย่างไรก็ตามมีหลายสิ่งที่ฉันไม่ชัดเจน:

  1. ไฟล์ข้อความต้องเป็นไฟล์ปกติหรือไม่ ในข้อความที่ตัดตอนมาข้างต้นมันไม่ได้บอกอย่างชัดเจนว่าไฟล์จะต้องเป็นไฟล์ปกติ

  2. ไฟล์สามารถพิจารณาเป็นไฟล์ข้อความได้หรือไม่หากมีอักขระหนึ่งตัวและหนึ่งตัวเท่านั้น (เช่นอักขระเดียวที่ไม่ได้ขึ้นบรรทัดใหม่ด้วย) ฉันรู้ว่าคำถามนี้อาจฟังดูไร้ค่า แต่พวกเขาใช้คำว่า "ตัวอักษร" แทน "หนึ่งตัวหรือมากกว่า" คนอื่นอาจไม่เห็นด้วย แต่ถ้าพวกเขาหมายถึง "หนึ่งตัวหรือมากกว่า" ฉันคิดว่าพวกเขาควรพูดอย่างชัดเจน

  3. ในข้อความที่ตัดตอนมาด้านบนมันทำให้การอ้างอิงถึง "เส้น" ฉันพบคำจำกัดความสี่บรรทัดในชื่อ: "Empty Line", "Display Line", "Inline Complete Line" และ "Line" ฉันควรจะอนุมานว่าพวกเขาหมายถึง "บรรทัด" เพราะพวกเขาละเว้น "ว่างเปล่า", "แสดง" และ "ไม่สมบูรณ์" - หรือทั้งสี่คำจำกัดความเหล่านี้รวมอยู่ในการพิจารณาว่าเป็นบรรทัดในข้อความที่ตัดตอนมาด้านบนหรือไม่

คำถามทั้งหมดที่มาหลังจากบล็อกข้อความนี้ขึ้นอยู่กับการอนุมานว่า "ตัวอักษร" หมายถึง "ตัวละครอย่างน้อยหนึ่งตัว":

  1. ฉันสามารถอนุมานได้อย่างปลอดภัยหรือไม่ว่าหากไฟล์นั้นว่างเปล่ามันไม่ใช่ไฟล์ข้อความเพราะมันไม่มีตัวอักษรอย่างน้อยหนึ่งตัว?

คำถามทั้งหมดที่มาหลังจากบล็อกข้อความนี้ขึ้นอยู่กับการอนุมานว่าในข้อความที่ตัดตอนมาข้างต้นบรรทัดนั้นถูกกำหนดเป็น "บรรทัด" และอีกสามคำจำกัดความที่มี "บรรทัด" ในชื่อของพวกเขาควรได้รับการยกเว้น:

  1. "ศูนย์" ใน "ศูนย์หรือมากกว่าบรรทัด" หมายความว่าไฟล์ยังสามารถพิจารณาเป็นไฟล์ข้อความได้หากมีอักขระอย่างน้อยหนึ่งตัวที่ไม่ได้ถูกยกเลิกด้วยการขึ้นบรรทัดใหม่

  2. "เป็นศูนย์หรือมากกว่าบรรทัด" หมายความว่าเมื่อมี "บรรทัด" เดียว (0 หรือมากกว่าตัวอักษรรวมทั้งขึ้นบรรทัดใหม่ยกเลิก) เข้ามาเล่นว่ามันจะผิดกฎหมายสำหรับบรรทัดสุดท้ายที่จะเป็น "สายไม่สมบูรณ์" (หรือมากกว่าหนึ่ง - อักขระขึ้นบรรทัดใหม่ท้ายไฟล์)?

  3. "ไม่มี [ไม่มีบรรทัด] เกินความยาว {LINE_MAX} ไบต์รวมถึงอักขระบรรทัดใหม่" หมายความว่ามีข้อ จำกัด จำนวนอักขระที่อนุญาตใน "บรรทัด" ใด ๆ ที่กำหนดในไฟล์ข้อความ (นอกเหนือจากค่าของ LINE_MAX บน Ubuntu 18.04 และ FreeBSD 11.1 คือ "2048")?


เป็นคำถามที่ดีแฮโรลด์! ทำให้การอภิปรายที่ดีของคำศัพท์ ต้องการฉันสามารถ upvote คำถามพิเศษครั้ง
Sergiy Kolodyazhnyy

คำตอบ:


23
  1. ไฟล์ข้อความต้องเป็นไฟล์ปกติหรือไม่ ในข้อความที่ตัดตอนมาข้างต้นมันไม่ได้บอกอย่างชัดเจนว่าไฟล์จะต้องเป็นไฟล์ปกติ

    ไม่มี ข้อความที่ตัดตอนมาแม้จะบันทึกเฉพาะอินพุตมาตรฐานเป็นไฟล์ข้อความที่เป็นไปได้ สาธารณูปโภคมาตรฐานอื่น ๆ เช่น make, โดยเฉพาะใช้ไฟล์อักขระพิเศษ เป็นแฟ้มข้อความ/dev/null

  2. ไฟล์สามารถพิจารณาเป็นไฟล์ข้อความได้หรือไม่หากมีอักขระหนึ่งตัวและหนึ่งตัวเท่านั้น (เช่นอักขระเดียวที่ไม่ได้ขึ้นบรรทัดใหม่ด้วย)

    อักขระนั้นต้องเป็น <newline> หรือนี่ไม่ใช่บรรทัดดังนั้นไฟล์ที่อยู่ในนั้นไม่ใช่ไฟล์ข้อความ ไฟล์ที่มีไบต์ 0A เป็นไฟล์ข้อความบรรทัดเดียว บรรทัดว่างคือบรรทัดที่ถูกต้อง

  3. ในข้อความที่ตัดตอนมาด้านบนมันทำให้การอ้างอิงถึง "เส้น" ฉันพบคำจำกัดความสี่บรรทัดในชื่อ: "Empty Line", "Display Line", "Inline Complete Line" และ "Line" ฉันควรจะอนุมานว่าพวกเขาหมายถึง "บรรทัด" เพราะพวกเขาละเว้น "ว่าง", "แสดง" และ "ไม่สมบูรณ์"

    มันไม่ได้อนุมานจริงๆมันเป็นเพียงสิ่งที่มันพูด คำว่า"บรรทัด" ได้รับการกำหนดตามบริบทที่เหมาะสมและนั่นคือสิ่งที่มันกำลังพูดถึง

  4. ฉันสามารถอนุมานได้อย่างปลอดภัยหรือไม่ว่าหากไฟล์นั้นว่างเปล่ามันไม่ใช่ไฟล์ข้อความเพราะมันไม่มีตัวอักษรอย่างน้อยหนึ่งตัว?

    ไฟล์ว่างประกอบด้วยเส้นศูนย์ (หรือมากกว่า) และเป็นไฟล์ข้อความ

  5. "ศูนย์" ใน "ศูนย์หรือมากกว่าบรรทัด" หมายความว่าไฟล์ยังสามารถพิจารณาเป็นไฟล์ข้อความได้หากมีอักขระอย่างน้อยหนึ่งตัวที่ไม่ได้ถูกยกเลิกด้วยการขึ้นบรรทัดใหม่

    ไม่ตัวละครเหล่านี้ไม่ได้ถูกจัดเป็นบรรทัด

  6. "เป็นศูนย์หรือมากกว่าบรรทัด" หมายความว่าเมื่อมี "บรรทัด" เดียว (0 หรือมากกว่าตัวอักษรรวมทั้งขึ้นบรรทัดใหม่ยกเลิก) เข้ามาเล่นว่ามันจะผิดกฎหมายสำหรับบรรทัดสุดท้ายที่จะเป็น "สายไม่สมบูรณ์" (หรือมากกว่าหนึ่ง - อักขระขึ้นบรรทัดใหม่ท้ายไฟล์)?

    มันไม่ผิดกฎหมายมันไม่ใช่แค่ไฟล์ข้อความ ยูทิลิตีที่ต้องการมอบไฟล์ข้อความอาจส่งผลเสียหากได้รับไฟล์นั้นแทน

  7. "ไม่มี [ไม่มีบรรทัด] เกินความยาว {LINE_MAX} ไบต์รวมถึงอักขระบรรทัดใหม่" หมายความว่ามีการ จำกัด จำนวนอักขระที่อนุญาตใน "บรรทัด" ที่กำหนดในไฟล์ข้อความใด ๆ

    ใช่.

คำจำกัดความนี้กำลังพยายามกำหนดขอบเขตบางอย่างเกี่ยวกับสิ่งที่ยูทิลิตี้ที่ใช้ข้อความ ( เช่นgrep ) จะยอมรับอย่างแน่นอน - ไม่มีอะไรเพิ่มเติม พวกเขายังมีอิสระที่จะยอมรับสิ่งต่าง ๆ อย่างเสรีมากขึ้นและบ่อยครั้งที่พวกเขาทำในทางปฏิบัติ พวกเขาได้รับอนุญาตให้ใช้บัฟเฟอร์ขนาดคงที่ในการประมวลผลบรรทัดเพื่อถือว่าบรรทัดใหม่ปรากฏขึ้นก่อนที่มันจะเต็มและอื่น ๆ คุณอาจอ่านสิ่งต่าง ๆ มากเกินไป


1
คุณแน่ใจเกี่ยวกับจุดที่ 2 หรือไม่? มาตรฐานระบุอย่างชัดเจนว่า " 0หรือมากกว่าบรรทัด" ดังนั้นprintf "a" > fileจะสร้างไฟล์ข้อความตามคำจำกัดความนั้น คำตอบของคุณสำหรับ 4 ดูเหมือนจะขัดแย้งกับคำตอบของคุณสำหรับ 2 และ 5 เนื่องจากคุณแนะนำให้touch fileสร้างไฟล์ข้อความในขณะที่printf "a" > fileไม่มี
terdon

4
@terdon: ฉันไม่เห็นความขัดแย้งในคำตอบของไมเคิล โดยทั่วไปดูเหมือนว่าเขาจะบอกว่าไฟล์ข้อความ POSIX เป็นไฟล์ใด ๆ ที่มีเนื้อหาตรงกับ regexp (.{0,M}\n)*(ทอดสมอโดยนัยและปลายทั้งสอง) ที่\nตรงกับขึ้นบรรทัดใหม่และ.ตรงกับตัวละครใด ๆ ที่ไม่ขึ้นบรรทัดใหม่และMเป็นตัวยึดสำหรับค่าตัวเลข LINE_MAX-1 โดยเฉพาะนี่หมายความว่าไฟล์ว่างเปล่าเป็นไฟล์ข้อความที่ถูกต้องซึ่งประกอบด้วยเส้นศูนย์ แต่ไฟล์ข้อความใด ๆ ที่ไม่ว่างจะต้องลงท้ายด้วยบรรทัดใหม่ (เพราะมิฉะนั้นจะมีบรรทัดที่ไม่สมบูรณ์และบรรทัดที่ไม่สมบูรณ์ไม่ใช่บรรทัด )
Ilmari Karonen

@Michael Homer เกี่ยวกับสิ่งที่ไฟล์ปกติมีตัวอย่างอื่นนอกเหนือจาก / dev / null? มันไม่ได้เป็นไฟล์ข้อความจริงๆเพราะมันมีตัวละครอย่างน้อยหนึ่งตัว
Harold Fischer

1
@HaroldFischer /dev/nullเป็นไฟล์ว่าง /dev/zeroคุณคิดว่าการ
Michael Homer

@HaroldFischer ไม่/dev/nullอ่านว่าว่างเปล่าเหมือนที่คุณไม่ได้รับข้อมูลเมื่อคุณอ่าน ฉันไม่แน่ใจว่ามันสมเหตุสมผลหรือไม่ที่จะต้องพิจารณาไฟล์ที่ไม่ปกติที่นี่เนื่องจากไฟล์ส่วนใหญ่นั้นเป็นแบบไดนามิก นั่นรวมถึงท่อ, ซ็อกเก็ต, อุปกรณ์ถ่านซึ่งโดยทั่วไปแล้วเป็นเพียงการขนส่งอินเทอร์เฟซไปยัง / จากเอนทิตีอื่น ๆ พวกเขาไม่ได้ถือชุดแบบคงที่ใด ๆ ของข้อมูลจึงต้องการทำให้รู้สึกมากขึ้นที่จะต้องพิจารณาคุณสมบัติของข้อมูลที่ถูกย้ายแทนของคุณสมบัติของไฟล์
ilkkachu

7

ตามที่กำหนดโดย POSIX:

ใช่ไฟล์ข้อความคือ (โดยทั่วไป):

ไฟล์ที่มีตัวอักษรจัดเป็นศูนย์หรือมากกว่าบรรทัด

มันจะมีประโยชน์ที่จะรวมถึงคำจำกัดความนี้:

สตริงอักขระ 3.92

ลำดับของอักขระที่ต่อเนื่องกันถูกยกเลิกโดยและรวมถึงไบต์แรกสุด

3.195 Line ไม่สมบูรณ์

ลำดับของอักขระที่ไม่ใช่ <newline> ตั้งแต่หนึ่งตัวขึ้นไปที่ท้ายไฟล์

3.206 สาย

ลำดับของอักขระที่ไม่ใช่ศูนย์ <newline> หรือมากกว่ารวมทั้งอักขระ <newline> ที่ยกเลิก

3.243 อักขระขึ้นบรรทัดใหม่ (<บรรทัดใหม่>)

อักขระที่อยู่ในเอาต์พุตสตรีมบ่งชี้ว่าการพิมพ์ควรเริ่มต้นที่จุดเริ่มต้นของบรรทัดถัดไป เป็นอักขระที่กำหนดโดย '\ n' ในภาษา C มันไม่ได้ระบุว่าตัวละครนี้เป็นลำดับที่แน่นอนส่งไปยังอุปกรณ์ส่งออกโดยระบบเพื่อให้การเคลื่อนไหวไปยังบรรทัดถัดไป

3.247 NUL

อักขระที่มีบิตทั้งหมดตั้งค่าเป็นศูนย์

โปรดทราบว่า "ไฟล์ข้อความ" จะไม่ NUL ไบต์


ดังนั้น:

  1. ไฟล์ข้อความต้องเป็นไฟล์ปกติหรือไม่
    ไม่ไม่จำเป็นต้องเป็น "ไฟล์ข้อความ" ถูกกำหนดในแง่ของสิ่งที่มันมีเมื่ออ่าน หากไฟล์มี "ศูนย์หรือมากกว่าบรรทัด" มันเป็นไฟล์ข้อความ ไฟล์บางไฟล์/dev/stdinอาจมีไฟล์ข้อความหากอ่านในคราวเดียวและไม่อ่านในครั้งถัดไป
  2. ไฟล์สามารถพิจารณาเป็นไฟล์ข้อความได้หรือไม่หากมีอักขระหนึ่งตัวและหนึ่งตัวเท่านั้น…
    ไม่นั่นเป็นบรรทัดที่ไม่สมบูรณ์ (3.195)
    ไฟล์ข้อความจะต้องไม่ใช่ "Inlines Complete Lines" เท่านั้น
  3. ฉันควรจะอนุมานว่าพวกเขาหมายถึง "สาย" ... ?
    ใช่คุณควรจะ.
  4. ฉันสามารถอนุมานได้อย่างปลอดภัยหรือไม่ว่าหากไฟล์ว่างเปล่ามันไม่ใช่ไฟล์ข้อความ ...
    ไม่ไฟล์ว่าง (อักขระศูนย์) เป็น "ไฟล์ข้อความ" ที่ถูกต้อง
    จากด้านบน: ... เป็นศูนย์หรือมากกว่านั้น ... . เส้นศูนย์ (อักขระศูนย์) เป็น "ไฟล์ข้อความ" ที่ถูกต้อง
  5. …พิจารณาว่าเป็นไฟล์ข้อความหรือไม่หากมีอักขระอย่างน้อยหนึ่งตัวที่ไม่ได้ขึ้นบรรทัดใหม่
    ไม่บรรทัด "ไม่สมบูรณ์" ไม่ใช่ "บรรทัด" ที่ถูกต้อง (ในทางเทคนิค)
  6. "ศูนย์" ใน "ศูนย์หรือมากกว่าบรรทัด" หมายความว่าไฟล์ยังสามารถพิจารณาเป็นไฟล์ข้อความได้หากมีอักขระอย่างน้อยหนึ่งตัวที่ไม่ได้ยกเลิกด้วยการขึ้นบรรทัดใหม่
    ไม่บรรทัดที่ไม่สมบูรณ์ไม่ใช่ "บรรทัด" ไฟล์ข้อความจะต้องไม่มีบรรทัดที่ไม่สมบูรณ์

  7. …มีข้อ จำกัด เกี่ยวกับจำนวนอักขระที่อนุญาตใน "Line" ที่กำหนดในไฟล์ข้อความ ... ?
    ใช่ไม่เกิน {LINE_MAX} ไบต์ (ต่างจากตัวอักษร) ในบรรทัดใด ๆ ของไฟล์ข้อความ "" ที่ถูกต้อง
    ค่าของ {LINE_MAX} นั้นมอบให้ในไฟล์ <limits.h>
    (อ่านขนาดบัฟเฟอร์ของบรรทัดที่มีความละเอียดใน C? ):

    {LINE_MAX}
    เว้นแต่จะระบุไว้เป็นอย่างอื่นความยาวสูงสุดเป็นไบต์ของบรรทัดอินพุตของยูทิลิตี (อินพุตมาตรฐานหรือไฟล์อื่น) เมื่อยูทิลิตีนี้ถูกอธิบายว่าเป็นการประมวลผลไฟล์ข้อความ ความยาวรวมถึงที่ว่างสำหรับลาก
    ค่าต่ำสุดที่ยอมรับได้: {_POSIX2_LINE_MAX}

    สำหรับระบบที่ใช้ GNU นั้น ไม่มีการ จำกัด ชุด (ยกเว้นหน่วยความจำ) :

    มาโคร: int LINE_MAX
    บรรทัดข้อความที่ใหญ่ที่สุดที่ยูทิลิตี้ POSIX.2 แบบข้อความสามารถรองรับได้ (ถ้าคุณใช้ยูทิลิตี้รุ่น GNU เหล่านี้แสดงว่าไม่มีข้อ จำกัด ตามจริงยกเว้นที่กำหนดโดยหน่วยความจำเสมือนที่มีอยู่ แต่ไม่มีวิธีที่ไลบรารีสามารถบอกคุณได้)

    ดูเหมือนว่าจะมีการกำหนดไว้ posix_lim.hให้เป็น 2048 (อย่างน้อยสำหรับระบบ 64 บิต linux GNU):

    $ grep -ri 'POSIX2_LINE_MAX' /usr/include/ 
    
    /usr/include/x86_64-linux-gnu/bits/xopen_lim.h:#define NL_LANGMAX       _POSIX2_LINE_MAX
    /usr/include/x86_64-linux-gnu/bits/posix2_lim.h:#define _POSIX2_LINE_MAX                2048
    /usr/include/x86_64-linux-gnu/bits/posix2_lim.h:#define LINE_MAX                _POSIX2_LINE_MAX
    

    มันอาจจะยังสามารถพบได้โดยใช้ยูทิลิตี้ POSIX getconf :

    $ getconf LINE_MAX
    2048
    

ที่เกี่ยวข้อง: เหตุใดไฟล์ข้อความควรลงท้ายด้วยการขึ้นบรรทัดใหม่


2
คำตอบนี้เป็นส่วนใหญ่ที่ถูกต้อง แต่คำตอบที่ถูกต้อง“แฟ้มข้อความจะต้องเป็นไฟล์ปกติ” คือไม่มี ไฟล์ประเภทใดก็ได้สามารถเป็นไฟล์ข้อความได้มันเป็นเรื่องของเนื้อหาประเภทไฟล์นั้นไม่เกี่ยวข้อง fileยูทิลิตี้รายงานเฉพาะประเภทของไฟล์สำหรับไฟล์พิเศษ แต่นั่นเป็นเพียงวิธีการทำงานของยูทิลิตี้การใช้งานfile - <…หรือ (Linux) file -s …เพื่อดูการวิเคราะห์พฤติกรรมของตนในเนื้อหาของแฟ้มสำหรับแฟ้มพิเศษ ไฟล์พิเศษสามารถมีเนื้อหาที่แตกต่างกันในแต่ละครั้งที่คุณเปิดมันดังนั้นอาจเป็นหรือเป็นไฟล์ข้อความในแต่ละครั้ง /dev/nullเป็นไฟล์ข้อความเสมอเพราะเนื้อหาเป็นไฟล์ข้อความเสมอ
Gilles 'หยุดความชั่วร้าย' Gilles

1
แทนที่จะใช้grepกับไฟล์คุณสามารถใช้getconfเพื่อรับค่า conf ของระบบเช่นgetconf LINE_MAXซึ่งคืนค่า 2048 (ไบต์) บนระบบของฉัน (Ubuntu 16.04)
heemayl

ฉันต้องการค้นหาไฟล์ที่กำหนดตัวแปรดังนั้นจึงจำเป็นต้อง grep และทำงาน (ค่อนข้างเร็ว) แต่ใช่getconfอนุญาตให้อ่านค่าปัจจุบันของการกำหนดค่า
ไอแซ
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.