ฉันต้องการส่งออกhello worldมากกว่า 20 ตัวอักษร
printf "%-20s :\n\n" 'hello world!!'
# Actual output
hello world!! :
# Wanted output
hello world!!========:
อย่างไรก็ตามฉันไม่ต้องการใช้ช่องว่าง แต่ใช้ " = " แทน ฉันจะทำอย่างไร
ฉันต้องการส่งออกhello worldมากกว่า 20 ตัวอักษร
printf "%-20s :\n\n" 'hello world!!'
# Actual output
hello world!! :
# Wanted output
hello world!!========:
อย่างไรก็ตามฉันไม่ต้องการใช้ช่องว่าง แต่ใช้ " = " แทน ฉันจะทำอย่างไร
คำตอบ:
คำตอบที่อัปเดตแล้วจะเป็นคำตอบทั่วไป ดูคำตอบอื่นฉันด้านล่างpritnfใช้การขยายตัวรั้งเปลือกเท่านั้นและ
$ str='Hello World!'
$ sed -r ':loop; s/ (=*):$/\1=:/; t loop' <<< "$(printf '%-20s:\n' "$str" )"
Hello World!========:
มันทำงานอย่างไร?
สิ่งนี้(=*):$/จะจับหนึ่งช่องว่างหนึ่งหรือมากกว่า=นั้นตามด้วยเครื่องหมายโคลอน:ในตอนท้ายของอินพุต เราสร้างกลุ่มของ=การจับคู่เป็นกลุ่มและ\1จะอ้างอิงกลับ
ด้วยความ:loopที่เรากำหนดป้ายชื่อloopและt loopมันจะข้ามไปยังป้ายว่าเมื่อs/ (=*):$/\1=:/ได้ทำทดแทนที่ประสบความสำเร็จ
ในส่วนที่แทนที่ด้วย\1=:มันจะเพิ่มจำนวนของ=s และกลับลำไส้ใหญ่ตัวเองไปยังจุดสิ้นสุดของสตริง
filler='===================='
string='foo'
printf '%s\n' "$string${filler:${#string}}"
จะช่วยให้
foo=================
${#string}คือความยาวของค่า$stringและ${filler:${#string}}เป็นสตริงย่อยของ$fillerจาก offset ${#string}เป็นต้นไป
ความกว้างรวมของการส่งออกจะเป็นที่ของความกว้างสูงสุดของหรือ$filler$string
สตริงฟิลเลอร์สามารถสร้างได้บนระบบที่มีjotอยู่แบบไดนามิก
filler=$( jot -s '' -c 16 '=' '=' )
(สำหรับ 16 =ในบรรทัด) ระบบ GNU อาจใช้seq:
filler=$( seq -s '=' 1 16 | tr -dc '=' )
ระบบอื่น ๆ อาจใช้ Perl หรือวิธีอื่นที่เร็วกว่าในการสร้างสตริงแบบไดนามิก
printfเพื่อสร้างตัวกรองที่เกือบจะมีอยู่ในทุกระบบและการขยายรั้งกับเชลล์ชอบbash/szh?
printfการขยายตัวรั้ง + ในbash?
printf "%.20s:\n\n" "$str========================="
%.20sรูปแบบการตัดสตริงอยู่ที่ไหน
วิธีหนึ่งในการทำ:
printf "====================:\r%s\n\n" 'hello world!!'
====================\rhello worldซึ่งอาจเป็นปัญหาถ้า OP ต้องการเก็บสิ่งนี้และไม่เพียงพิมพ์ไปที่หน้าจอ
echo -e '=================\rHello World!!'แต่มีปัญหาเช่นเดียวกับ @terdon ชี้ให้เห็นว่า
echo เกือบจะดีกว่าด้วยเหตุผลหลายประการ -eprintfecho
วิธีการ Perl:
$ perl -le '$k="hello world!!"; while(length($k)<20){$k.="=";} print "$k\n"'
hello world!!=======
หรือดีกว่า @SatoKatsura ชี้ให้เห็นในความคิดเห็น:
perl -le '$k = "hello world!!"; print $k, "=" x (20-length $k), "\n"'
หากคุณต้องการสนับสนุนอักขระหลายไบต์ UTF ให้ใช้:
PERL_UNICODE='AS' perl -le '$k = "hello world!!"; print $k, "=" x (20-length $k), "\n"'
แนวคิดเดียวกันในเปลือก:
v='hello world!!'; while [ ${#v} -lt 20 ]; do v="$v""="; done; printf '%s\n\n' "$v"
perl -le '$k = "hello world!!"; print $k, "=" x (20-length $k), "\n"'คุณไม่จำเป็นต้องห่วง: อย่างไรก็ตามวิธีนี้ (และโซลูชันอื่น ๆ ทั้งหมดที่โพสต์จนถึง) จะหยุดพักหากมีอักขระหลายไบต์เข้ามาเกี่ยวข้อง
perl6อาจมีวิธีการทำอย่างถูกต้องแม้จะมีตัวละครหลายไบต์ แต่ในทางกลับกันperl6มันน่ารำคาญในหลาย ๆ ด้าน
PERL_UNICODE='AS'SatōKatsuraดีสำหรับการเรียงลำดับของสิ่งง่ายๆนี้ก็ควรจะพอเพียงชุด ตัวอย่างเช่น: printf '%s' nóóös | perl -nle 'print length($_)'พิมพ์ 8 ("ผิด") ในขณะที่printf '%s' nóóös | PERL_UNICODE='AS' perl -nle 'print length($_)'พิมพ์ 5 ("ถูกต้อง")
อีกวิธีหนึ่งคือใช้printfคำสั่งเท่านั้นและสร้างรูปแบบการขยายตัวอักขระแรกโดยShell Brace Expansion(คุณสามารถใส่ท้ายด้วยพื้นที่จัดรูปแบบตัวเลข you ที่คุณต้องการพิมพ์{1..end}) และรับเฉพาะอักขระแรกทุกตัวของมัน%.1sซึ่งเป็น=s แล้วพิมพ์ความยาว 20 อักขระแรกเท่านั้น %.20sพื้นที่ที่ นี่เป็นวิธีที่ดีกว่าในการมีตัวอักษร / คำซ้ำ ๆ
printf '%.20s:\n' "$str$(printf '%.1s' ={1..20})"
Hello World!!=======:
คำอธิบาย:
โดยปกติแล้วเป็นBrace Expansionให้เชลล์ขยาย{1..20}ดังต่อไปนี้ถ้าเราพิมพ์เหล่านั้น
printf '%s ' {1..20}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
ดังนั้นเมื่อเพิ่มเครื่องหมายเท่ากับ={1..20}เชลล์จะขยายดังต่อไปนี้
printf '%s ' ={1..20}
=1 =2 =3 =4 =5 =6 =7 =8 =9 =10 =11 =12 =13 =14 =15 =16 =17 =18 =19 =20
และด้วยความprintf '%.1s'ที่เป็นจริงหมายถึงprintf '%WIDE.LENGTH'เรากำลังพิมพ์เพียงหนึ่งความยาวของผู้ที่อยู่ข้างต้นด้วยการเริ่มต้นWIDE1 ดังนั้นจะส่งผล=เฉพาะ s และซ้ำ 20 ครั้งเอง
ขณะนี้printf '%.20s:\n'เรากำลังพิมพ์ความยาวเพียง 20 $strและถ้าความยาว$str<20 ส่วนที่เหลือจะใช้เวลาจาก=s ที่สร้างมาเติมด้วยแทนที่จะเป็นช่องว่าง