Bash - ลำดับของตัวเลขในบรรทัดเดียวกัน


20

ฉันรู้ว่าคำสั่งseqเพื่อสร้างลำดับของจำนวนเต็มหนึ่งต่อบรรทัด แต่ฉันต้องการถามคำถามสองข้อ:

  1. เป็นไปได้ที่จะเขียนตัวเลขของลำดับในบรรทัดเดียวกันหรือไม่?

  2. เป็นไปได้ไหมที่จะสร้างสตริงที่ทำตามลำดับตัวเลขโดยคั่นด้วยช่องว่าง


เชลล์ปฏิบัติต่อบรรทัดใหม่เช่นช่องว่างเป็นตัวคั่นอาร์กิวเมนต์ ดังนั้นในขณะที่ seq มีอาร์กิวเมนต์ตัวแยกและสิ่งที่ง่ายกว่าที่จะบอกก็คือผู้ใช้echo $(seq 1 10)
348445

1
@ user3188445 มันเป็นตัวดำเนินการแยก + glob ที่ทำเช่นนั้น (ที่ใช้ตัวแปรพิเศษของ IFS ที่โดยค่าเริ่มต้นจะมีช่องว่างและขึ้นบรรทัดใหม่ แต่สามารถเปลี่ยนแปลงได้) มันแยกจากคำโทเค็นที่ทำโดยเชลล์
Stéphane Chazelas

คำตอบ:



21

GNU seqใช้ตัว-sเลือกseparator ( ):

$ seq -s ' ' 1 5
1 2 3 4 5

$ var="$(seq -s ' ' 1 5)"
$ echo "$var"
1 2 3 4 5

1
echo $(seq 5)ทำงานได้ดี

13

พกพาไปสู่เชลล์ทั้งหมดและระบบใด ๆ ที่มี seq (ตามที่ติดแท็กคำถามนี้)

หากเริ่มต้นคือ 1:

$ echo $(seq 10)
1 2 3 4 5 6 7 8 9 10

มิฉะนั้น:

$ echo $(seq 5 10)
5 6 7 8 9 10

ด้วย bc:

$ echo $(echo "for (i=0;i<=1000;i++) i"| bc)

ในทุบตี

echo {1..10}

บันทึก:

โซลูชัน echo นี้จะทำงานหากค่าของ IFS มีการขึ้นบรรทัดใหม่ซึ่งจะทำตามค่าเริ่มต้น
โดยค่าเริ่มต้นไอเอฟเอมีการตั้งค่าลำดับ<พื้นที่> <แท็บ> <newline> และจะถูกรีเซ็ตสำหรับการเริ่มเชลล์ใหม่ทุกครั้ง แต่หากคุณมีข้อกังวลว่าอาจมีการเปลี่ยนแปลงในบางกรณีเรามีวิธีแก้ปัญหาหลายอย่าง

ภายใต้ bash, zsh, ksh เพียงใช้: IFS = $ '\ t \ n' (ข้ามคำตอบที่เหลือทั้งหมดนี้)


อย่างไรก็ตามการรีเซ็ตค่าของไอเอฟเอภายใต้การดวลจุดโทษอาจจะซับซ้อนอ่านรายละเอียดที่สมบูรณ์ที่นี่

ยกเลิกการตั้งค่า IFS

$ unset IFS; echo $(seq 5 10)                           #Always work.

จะทำงานเสมอ โดยมีเงื่อนไขว่าจะมีโค้ดด้านล่าง (หรือสคริปต์เด็ก) OldIFS="$IFS"ที่จำเป็นชุดไอเอฟเอเช่นสคริปต์ซึ่งจะไม่มี

ทางออกที่ถูกต้อง

ใช้เคล็ดลับสำหรับดวลจุดโทษ:

sh -c 'IFS="$(printf " \t\nx")"; IFS="${IFS%x}"; printf "$IFS"|xxd'  # correct.

ความคิดเห็นไม่ได้มีไว้สำหรับการอภิปรายเพิ่มเติม การสนทนานี้ได้รับการย้ายไปแชท
terdon

1
การใช้งาน sh ส่วนใหญ่จะไม่สนใจ IFS ที่พบในสภาพแวดล้อม (ข้อยกเว้นบางอย่างคืออนุพันธ์ของเถ้า, บอร์นเชลล์รุ่นเก่ามากและบางรุ่นล่าสุดของ posh) โปรดทราบว่าคุณสามารถทำIFS='<space><tab><newline>' ที่เหล่านั้น<space>, <tab>, <newline>กำลังที่สอดคล้องกันอักขระตามตัวอักษร
Stéphane Chazelas


0
seq 10 |xargs

...หรือ...

seq 10 |paste -s -

คำสั่งทั้งสองข้างต้นจะแยกจำนวนเต็มด้วยช่องว่าง xargsค่าเริ่มต้นที่จะเลียนแบบ/bin/echoและเพื่อให้แต่ละจำนวนเต็มถูกคั่นด้วยช่องว่างเดียว มันจะเริ่มต้นที่ความยาวบรรทัดคำสั่งสูงสุด 128K แม้ว่า คุณสามารถปรับสิ่งนี้ ...

seq 100000 | xargs -s2093009 | wc -l

... พิมพ์ 1. ฉันค่า-sที่นี่ไม่ได้ตามอำเภอใจ - ฉันได้รับหลังจากลองใช้ค่าที่สูงขึ้น(ซึ่งเห็นได้ชัดว่าทำงานได้อยู่แล้ว)แต่หลังจากนั้นxargsพิมพ์ข้อความที่เป็นประโยชน์:

-s value should be <2093010

pasteเป็นหนึ่งในสอง(เพื่อความรู้ของฉัน) POSIX - ทำนองคลองธรรมสาธารณูปโภคสำหรับการจัดการบรรทัดความยาวโดยพล:

pasteข้อกำหนดการใช้งานแอปพลิเคชัน :

ส่วนใหญ่ของสาธารณูปโภคมาตรฐานการทำงานกับไฟล์ข้อความ cutยูทิลิตี้ที่สามารถใช้ในการเปิดไฟล์ที่มีความยาวสายพลเป็นชุดของไฟล์ข้อความที่มีข้อมูลเดียวกัน pasteยูทิลิตี้สามารถนำมาใช้ในการสร้าง (หรือสร้าง) ไฟล์ที่มีความยาวเส้นโดยพลการ

ไฟล์ข้อความ

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

pasteเริ่มต้นที่ตัวคั่นแท็บและดังนั้นจะมีแท็บระหว่างแต่ละจำนวนเต็มตามคำสั่งที่สอง คุณสามารถ...

seq 10 |paste -sd ' ' - 

... ใช้-dสวิตช์ elimiter เพื่อเปลี่ยนพฤติกรรมนั้น


seq 10 | xargsทำงานได้ดี แต่เป็นเพราะคำสั่งขีด จำกัด ของสายseq 100000 | xargsoutputs 5 \nเส้นคั่น (ในระบบของฉัน)
Peter.O

@ Peter.O - paste and cut` เป็นโปรแกรมอรรถประโยชน์ POSIX สองแบบสำหรับการทำงานกับบรรทัดที่มีความยาวอนุญาโตตุลาการ ที่กล่าวว่าxargs | xargsเป็นตัวเลือก หรืออื่น ๆseq 100000|tr \\n \
mikeserv

ความคิดเห็นไม่ได้มีไว้สำหรับการอภิปรายเพิ่มเติม การสนทนานี้ได้รับการย้ายไปแชท
terdon

@BinaryZebra - ไม่มันไม่ - ไม่เหมือนที่คุณคิด ทำไมไม่ลองตั้งค่า$IFSเป็นตัวเลข? และในbashGodawful ของมันช้าอยู่ดี ในคำตอบของคุณคุณพูดถึงsh- คุณไม่จำเป็นต้องตั้งค่า$IFSในบริบทนั้น - มันจะถูกส่งผ่านทางสภาพแวดล้อมหากตั้งไว้ที่นั่น และมันก็ไม่ได้สั้นไปกว่าseq 100000|paste -sจังหวะที่มันมีประสิทธิภาพ 5: 1 และpasteไม่ได้มาด้วย gotchas ใด ๆ
mikeserv

@BinaryZebra - มาทำไมฉันถึงโกหก? ฉันมีโปรไฟล์คำตอบขนาดใหญ่ในเว็บไซต์นี้เพราะฉันชอบเผยแพร่ข้อมูลที่ผิดหรือไม่? หรืออาจเป็นเพราะฉันชอบช่วยเหลือผู้คนและสนุกกับความท้าทายในการเรียนรู้ในขณะที่ฉันทำ? คุณคิดว่าแบบไหนมีเหตุผลมากกว่ากัน ฉันชอบ$IFS- ฉันใช้มันตลอดเวลา - แต่ฉันจะไม่ใช้มันจนกว่าฉันจะตั้งค่าและคุณไม่ควรทำ โดยเฉพาะอย่างยิ่งคุณไม่ควรแนะนำให้คนแปลกหน้าแบบสุ่มที่ไม่รู้ว่าควรทำเช่นนั้น อย่าปล่อยให้โอกาสมันเป็นโปรแกรมคอมพิวเตอร์ มันเป็นข้อผิดพลาดถ้ามันทำงานโดยไม่คาดคิด - ทำไมจึงอนุญาตให้ทำอย่างนั้น?
mikeserv
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.