ฉันต้องการส่งออก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
เกือบจะดีกว่าด้วยเหตุผลหลายประการ -e
printf
echo
วิธีการ 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 ที่สร้างมาเติมด้วยแทนที่จะเป็นช่องว่าง