มีวิธีป้องกันไม่ให้ sed ตีความหมายของสตริงการแทนที่หรือไม่? [ปิด]


16

หากคุณต้องการแทนที่คำหลักด้วยสตริงที่ใช้ sed, sed พยายามอย่างหนักเพื่อตีความสตริงการแทนที่ของคุณ หากสตริงการแทนที่มีอักขระที่พิจารณาว่าพิเศษเช่นอักขระ '/' สตริงนั้นจะล้มเหลวเว้นแต่แน่นอนว่าคุณหมายถึงสตริงการแทนที่ของคุณที่จะมีอักขระที่บอกให้รู้ว่าจะต้องทำอย่างไร

Ex:

VAR="hi/"

sed "s/KEYWORD/$VAR/g" somefile

มีวิธีใดที่จะบอกว่าอย่าพยายามตีความสตริงการแทนที่สำหรับอักขระพิเศษ? สิ่งที่ฉันต้องการคือสามารถแทนที่คำหลักในไฟล์ด้วยเนื้อหาของตัวแปรไม่ว่าเนื้อหานั้นจะเป็นอะไร


หากคุณต้องการใส่อักขระพิเศษลงไปsedและไม่ให้เป็นอักขระพิเศษเพียงแค่แบ็กสแลชหนีออกมา VAR='hi\/'ไม่มีปัญหาดังกล่าว
สัญลักษณ์แทน

6
ทำไมต้องโหวตทั้งหมด ดูเหมือนว่าเป็นคำถามที่สมเหตุสมผลอย่างสมบูรณ์แบบสำหรับฉัน
roaima

sed(1)เพียงตีความสิ่งที่ได้รับ ในกรณีของคุณจะได้รับผ่านการแก้ไขเชลล์ ฉันเชื่อว่าคุณไม่สามารถทำตามที่คุณต้องการ แต่ตรวจสอบคู่มือ ฉันรู้ใน Perl (ซึ่งทำให้การsedแทนที่ผ่านได้มีการแสดงออกปกติยิ่งขึ้น) คุณสามารถระบุสตริงที่จะต้องดำเนินการตามตัวอักษรอีกครั้งตรวจสอบคู่มือ
vonbrand

คำตอบ:


5

คุณสามารถใช้ Perl แทน sed ด้วย-p(สมมติว่า loop over input) และ-e(ให้โปรแกรมบนบรรทัดคำสั่ง) ด้วย Perl คุณสามารถเข้าถึงตัวแปรสภาพแวดล้อมได้โดยไม่ต้องแก้ไขสิ่งเหล่านี้ในเชลล์ โปรดทราบว่าตัวแปรจะต้องมีการส่งออก :

export VAR='hi/'
perl -p -e 's/KEYWORD/$ENV{VAR}/g' somefile

หากคุณไม่ต้องการที่จะส่งออกตัวแปรทุกที่เพียงแค่ให้มันสำหรับกระบวนการนั้นเท่านั้น:

PATTERN="$VAR" perl -p -e 's/KEYWORD/$ENV{PATTERN}/g' somefile

โปรดทราบว่าไวยากรณ์การแสดงออกปกติของ Perl นั้นโดยปกติแล้วจะแตกต่างจากของ sed เล็กน้อย


สิ่งนี้ดูมีแนวโน้มมาก แต่เมื่อทำการทดสอบฉันได้รับข้อผิดพลาด "รายการอาร์กิวเมนต์ยาวเกินไป" เพราะสตริงการแทนที่ของฉันยาวเกินไปซึ่งสมเหตุสมผล - การใช้วิธีนี้เรากำลังใช้สตริงการแทนที่ทั้งหมดเป็นส่วนหนึ่งของอาร์กิวเมนต์ที่เราให้ ถึง Perl ดังนั้นจึงมีข้อ จำกัด เกี่ยวกับระยะเวลาที่สามารถใช้
Tal

1
ไม่มันจะไปในPATTERN ตัวแปรสภาพแวดล้อมไม่ใช่อาร์กิวเมนต์ ในกรณีใด ๆ ข้อผิดพลาดนี้จะเป็นที่ที่คุณจะได้รับอย่างเท่าเทียมกันถ้าคุณใช้E2BIG sed
Antti Haapala

4

มีเพียง 4 ตัวอักษรพิเศษในส่วนทดแทนที่มี: \, &, ขึ้นบรรทัดใหม่และตัวคั่น ( โทษ )

$ VAR='abc/def&ghi\foo
next line'

$ repl=$(sed -e 's/[&\\/]/\\&/g; s/$/\\/' -e '$s/\\$//' <<<"$VAR")

$ echo "$repl"
abc\/def\&ghi\\foo\
next line

$ echo ZYX | sed "s/Y/$repl/g"
Zabc/def&ghi\foo
next lineX

นี่เป็นปัญหาเดียวกับวิธีแก้ปัญหาของ Antti - ถ้าสตริงการแทนที่ยาวเกินความยาวที่กำหนดคุณจะได้รับข้อผิดพลาด "รายการอาร์กิวเมนต์ยาวเกินไป" นอกจากนี้จะเกิดอะไรขึ้นถ้าสตริงการแทนที่มี '[', ']', '*', '.' และอักขระอื่น ๆ จะไม่ตีความเหล่านั้นจริง ๆ หรือไม่
Tal

ด้านการเปลี่ยนs///เป็นไม่แสดงออกปกติก็จริงๆเพียงสตริง (ยกเว้นทับขวา-หนีและ&) หากสายอักขระการเปลี่ยนยาวเกินไป shell one-liner ไม่ใช่คำตอบของคุณ
เกล็

รายการที่มีประโยชน์มากตัวอย่างเช่นหากสตริงการแทนที่ของคุณคือข้อความที่เข้ารหัส base64 (เช่นการแทนที่ตัวยึดตำแหน่งด้วยคีย์ SHA256) จากนั้นเป็นเพียงตัวคั่นที่ต้องกังวล
Heath Raftery

2

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

ในviคุณสามารถหลบหนีตัวควบคุมใด ๆ โดยพิมพ์ Ctrl-V (เขียนมากขึ้นเป็น^V) ดังนั้นหากคุณใช้อักขระควบคุมบางตัว (ฉันมักใช้^Aเป็นตัวคั่นในกรณีเหล่านี้) sedคำสั่งของคุณจะหยุดก็ต่อเมื่ออักขระที่ไม่พิมพ์นั้นปรากฏอยู่ในตัวแปรที่คุณกำลังปล่อย

ดังนั้นคุณจะพิมพ์"s^V^AKEYWORD^V^A$VAR^V^Ag"และสิ่งที่คุณจะได้รับ (ในvi) จะมีลักษณะ:

sed "s^AKEYWORD^A$VAR^Ag" somefile

สิ่งนี้จะใช้ได้ตราบใดที่$VARไม่มีอักขระที่ไม่พิมพ์^Aซึ่งไม่น่าเป็นไปได้


แน่นอนว่าถ้าคุณป้อนข้อมูลของผู้ใช้เป็นมูลค่าการ$VARเดิมพันทั้งหมดจะถูกปิดและคุณควรทำให้การป้อนข้อมูลของคุณดีขึ้นโดยไม่ต้องพึ่งพาตัวควบคุมที่ยากต่อการพิมพ์สำหรับผู้ใช้ทั่วไป


แม้ว่าจะต้องระวังมากกว่าตัวคั่นสตริง ตัวอย่างเช่น&เมื่ออยู่ในสตริงการแทนที่หมายถึง "ข้อความทั้งหมดที่ตรงกัน" เช่นs/stu../my&/จะแทนที่ "เนื้อหา" ด้วย "mystuff", "stung" ด้วย "mystung" ฯลฯ ดังนั้นหากคุณอาจมีอักขระใด ๆในตัวแปรที่คุณวางอยู่ในฐานะสตริงแทนที่ แต่คุณต้องการใช้ตัวอักษร ค่าของตัวแปรเท่านั้นจากนั้นคุณมีข้อมูลที่ถูกต้องในการฆ่าเชื้อก่อนที่คุณจะสามารถใช้ตัวแปรเป็นสตริงการแทนที่sedได้ (การฆ่าเชื้อข้อมูลสามารถทำได้ด้วยsedเช่นกัน)


นั่นเป็นประเด็นของฉัน - การแทนที่สตริงด้วยสตริงอื่นเป็นการดำเนินการที่ง่ายมาก จำเป็นหรือไม่ที่จะต้องมีความซับซ้อนเช่นเดียวกับการหาว่าตัวละครตัวไหนที่ไม่ชอบและการใช้ sed เพื่อฆ่าเชื้ออินพุตของตัวเอง? นั่นฟังดูน่าขันและซับซ้อนโดยไม่จำเป็น ฉันไม่ใช่โปรแกรมเมอร์มืออาชีพ แต่ฉันค่อนข้างมั่นใจว่าฉันสามารถเขียนโค้ดฟังก์ชั่นเล็ก ๆ ที่แทนที่คำหลักด้วยสตริงในภาษาที่ฉันเคยเจอมาแล้วรวมถึงทุบตี - ฉันแค่หวังลีนุกซ์ธรรมดา วิธีการแก้ปัญหาโดยใช้เครื่องมือที่มีอยู่ - ฉันไม่อยากจะเชื่อเลยว่าไม่มีใครอยู่ข้างนอกนั่น
Tal

1
@Tal หากสตริงการแทนที่ของคุณคือ "100s ของหน้ายาว" ตามที่คุณพูดถึงในความคิดเห็นอื่น ... คุณแทบจะไม่สามารถเรียกได้ว่าเป็นกรณีการใช้ "แบบง่าย" คำตอบที่นี่คือ Perl โดยวิธี - ฉันเพิ่งไม่ได้เรียนรู้ Perl ความซับซ้อนที่นี่มาจากความจริงที่ว่าคุณต้องการที่จะช่วยให้การป้อนข้อมูลโดยพลการใด ๆ ที่เป็นสตริงทดแทนในregex
ไวด์การ์ด

มีวิธีแก้ปัญหาอื่น ๆ อีกมากมายที่คุณสามารถใช้ได้ส่วนใหญ่ง่ายมาก ตัวอย่างเช่นถ้าสตริงทดแทนของคุณเป็นจริงตามสายและไม่จำเป็นที่จะแทรกอยู่ในช่วงกลางของเส้นใช้sed's iคำสั่ง nsert แต่sedไม่ใช่เครื่องมือที่ดีสำหรับการประมวลผลข้อความจำนวนมากในรูปแบบที่ซับซ้อน awkผมจะโพสต์คำตอบอื่นที่แสดงวิธีการทำเช่นนี้กับ
ไวด์การ์ด

1

คุณสามารถใช้ a ,หรือ a |แทนได้และมันจะใช้เป็น seperator และในทางเทคนิคคุณสามารถใช้อะไรก็ได้

จากหน้าคน

\cregexpc
           Match lines matching the regular expression regexp.  The  c  may
      be any character.

อย่างที่คุณเห็นคุณควรเริ่มต้นด้วย \ ก่อนตัวคั่นที่จุดเริ่มต้นจากนั้นคุณสามารถใช้มันเป็นตัวแยกได้

จากเอกสารhttp://www.gnu.org/software/sed/manual/sed.html#The-_0022s_0022-Command :

The / characters may be uniformly replaced by any other single character 
within any given s command.

The / character (or whatever other character is used in its stead) can appear in 
the regexp or replacement only if it is preceded by a \ character.

ตัวอย่าง:

sed -e 'somevar|s|foo|bar|'
echo "Hello all" | sed "s_all_user_"
echo "Hello all" | sed "s,all,user,"

echo "Hello/ World" | sed "s,Hello/,Neo,"


คุณกำลังพูดถึงอนุญาตให้ใช้อักขระตัวเดียวที่ระบุในสตริงการแทนที่ - ในกรณีนี้ "/" ฉันกำลังพูดถึงการป้องกันไม่ให้พยายามตีความสตริงการแทนที่โดยสิ้นเชิง ไม่ว่าคุณจะใช้อักขระใด ("/", ",", "|" ฯลฯ ) คุณก็เสี่ยงที่จะมีตัวละครนั้นปรากฏขึ้นในสตริงการแทนที่ นอกจากนี้ตัวละครเริ่มต้นไม่ใช่ตัวละครพิเศษเพียงอย่างเดียวที่ดึงดูดความสนใจเท่านั้นใช่ไหม?
Tal

@ ไม่สามารถนำสิ่งใดมาทดแทนได้/และมันจะเพิกเฉยต่อ/ความสุขอย่างที่ฉันเพิ่งจะชี้ให้เห็น .. ในความเป็นจริงคุณยังสามารถค้นหาและแทนที่มันในสตริง >>> ฉันได้แก้ไขด้วยตัวอย่าง >>> เหล่านี้ สิ่งต่าง ๆ นั้นไม่ปลอดภัยและคุณจะพบกับเพื่อนที่ฉลาดกว่าเสมอ
user3566929

@ ทำไมคุณต้องการป้องกันไม่ให้ตีความ? ฉันหมายถึงนั่นคือการใช้งานsedตั้งแต่แรกโครงการของคุณคืออะไร
user3566929

ทั้งหมดที่ฉันต้องการคือการแทนที่คำหลักด้วยสตริง sed ดูเหมือนจะเป็นวิธีที่พบได้บ่อยที่สุดในการทำสิ่งนี้ใน linux สตริงสามารถมีความยาวได้ 100 หน้า ฉันไม่ต้องการพยายามที่จะทำให้สตริงสะอาดเพื่อที่ว่า sed จะไม่ประหลาดเมื่ออ่านมัน - ฉันต้องการให้สามารถจัดการกับตัวละครใด ๆ ในสตริงและโดย "จัดการ" ฉันหมายถึงไม่พยายามค้นหาเวทย์มนตร์ ความหมายภายใน
Tal

1
@Tal, bashคือไม่ได้สำหรับการจัดการสตริง ที่ทุกคนเลย มันเป็นสำหรับการจัดการไฟล์และการประสานงานคำสั่ง มันเกิดขึ้นที่จะมีบางส่วนที่สร้างขึ้นในฟังก์ชั่นที่มีประโยชน์สำหรับสตริง แต่ จำกัด จริงๆและไม่ได้เร็วมากเลยถ้านั่นคือสิ่งที่สำคัญที่คุณกำลังทำ ดูที่"ทำไมการใช้เชลล์ลูปในการประมวลผลข้อความจึงถือว่าไม่เหมาะสม" เครื่องมือบางอย่างที่ได้รับการออกแบบมาสำหรับการประมวลผลข้อความในการสั่งซื้อจากโรงแรมระดับล่างมากที่สุดเพื่อให้มีประสิทธิภาพมากที่สุด: sed, awkและ Perl
สัญลักษณ์แทน

1

หากเป็นแบบบรรทัดและมีเพียงหนึ่งบรรทัดที่จะแทนที่ฉันขอแนะนำให้เตรียมไฟล์ของตัวเองด้วยการแทนที่บรรทัดโดยใช้การprintfจัดเก็บบรรทัดแรกนั้นในsedพื้นที่พักไว้และวางลงตามที่ต้องการ ด้วยวิธีนี้คุณไม่ต้องกังวลกับตัวละครพิเศษเลย (ข้อสันนิษฐานเดียวที่นี่คือ$VARมีข้อความบรรทัดเดียวโดยไม่มีบรรทัดใหม่ซึ่งเป็นสิ่งที่คุณพูดในความคิดเห็นแล้ว) นอกเหนือจากการขึ้นบรรทัดใหม่ VAR อาจมีสิ่งใด ๆและสิ่งนี้จะทำงานโดยไม่คำนึงถึง

VAR=whatever
{ printf '%s\n' "$VAR";cat somefile; } | sed '1{h;d;};/KEYWORD/g'

printf '%s\n'จะพิมพ์เนื้อหา$VARเป็นสตริงตัวอักษรโดยไม่คำนึงถึงเนื้อหาตามด้วยบรรทัดใหม่ ( echoจะทำสิ่งอื่น ๆ ในบางกรณีเช่นหากเนื้อหา$VARเริ่มต้นด้วยเครื่องหมายยัติภังค์ - มันจะถูกตีความว่าเป็นธงตัวเลือกที่ถูกส่งผ่านไปecho)

วงเล็บจะใช้ในการย่อหน้าการส่งออกของprintfเนื้อหาของที่มันผ่านไปsomefile sedช่องว่างแยกวงเล็บปีกกาด้วยตัวเองเป็นสิ่งสำคัญที่นี่เช่นเดียวกับอัฒภาคก่อนที่จะปิดวงเล็บปีกกา

1{h;d;};เป็นsedคำสั่งที่จะเก็บบรรทัดแรกของข้อความในsed's พื้นที่ถือแล้วdหนึ่งคำสาย (แทนที่จะพิมพ์)

/KEYWORD/KEYWORDนำไปใช้ดำเนินการต่อไปกับเส้นทั้งหมดที่มี การดำเนินการคือget ซึ่งรับเนื้อหาของพื้นที่พักและวางแทนที่พื้นที่รูปแบบ - กล่าวอีกนัยหนึ่งคือบรรทัดปัจจุบันทั้งหมด (นี่ไม่ใช่เพื่อแทนที่เพียงส่วนหนึ่งของบรรทัด) พื้นที่เก็บข้อมูลจะไม่ถูกลบออกโดยวิธีการเพียงคัดลอกลงในพื้นที่รูปแบบแทนที่สิ่งที่มีอยู่

หากคุณต้องการที่จะยึด regex ของคุณดังนั้นมันจะไม่ตรงกับบรรทัดที่มี KEYWORD แต่เพียงบรรทัดที่ไม่มีอะไรอื่นในบรรทัดนอกจาก KEYWORD ให้เพิ่มจุดเริ่มต้นของบรรทัด anchor ( ^) และ end of line anchor ( $) เพื่อ regex ของคุณ:

VAR=whatever
{ printf '%s\n' "$VAR";cat somefile; } | sed '1{h;d;};/^KEYWORD$/g'

ดูดีมากถ้า VAR ของคุณยาวหนึ่งบรรทัด ฉันพูดถึงในความคิดเห็นว่า VAR "สามารถยาวได้ 100 หน้า" แทนที่จะเป็นหนึ่งบรรทัด ขอโทษสำหรับความสับสน.
Tal

0

คุณสามารถ backslash-escape เครื่องหมายทับซ้ายในสตริงการแทนที่ของคุณโดยใช้การขยายพารามิเตอร์การแทนที่รูปแบบของ Bash มันยุ่งนิดหน่อยเพราะสแลชข้างหน้านั้นจะต้องหนีด้วย Bash ด้วย

$ var='a/b/c';var="${var//\//\\/}";echo 'this is a test' | sed "s/i/$var/g"

เอาท์พุต

tha/b/cs a/b/cs a test

คุณสามารถใส่พารามิเตอร์ส่วนขยายลงในคำสั่ง sed ของคุณได้โดยตรง:

$ var='a/b/c';echo 'this is a test' | sed "s/i/${var//\//\\/}/g"

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

อีกตัวเลือกหนึ่งคือการใช้สคริปต์ที่เขียนใน awk, perl หรือ Python หรือโปรแกรม C เพื่อทำการทดแทนของคุณแทนที่จะใช้ sed


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

import sys

#Get the keyword and replacement texts from the command line
keyword, replacement = sys.argv[1:]
for line in sys.stdin:
    #Strip any trailing whitespace
    line = line.rstrip()
    if line == keyword:
        line = replacement
    print(line)

นี่เป็นอีกวิธีหนึ่งในการฆ่าเชื้อการป้อนข้อมูลและไม่ใช่วิธีการที่ยอดเยี่ยมเนื่องจากเป็นเพียงการจัดการอักขระหนึ่งตัว ('/') ดังที่ไวลด์การ์ดชี้ให้เห็นมีข้อควรระวังมากกว่าเพียงแค่สตริงตัวคั่น
Tal

โทรอย่างยุติธรรม ตัวอย่างเช่นหากข้อความการแทนที่มีลำดับการย้อนกลับของเครื่องหมายแบคสแลชพวกเขาจะถูกตีความซึ่งอาจไม่เป็นที่ต้องการ วิธีหนึ่งที่สามารถแปลง chars ที่มีปัญหา (หรือของทั้งหมด) ไปเป็น\xescape sequences ได้ หรือจะใช้โปรแกรมที่สามารถจัดการกับอินพุตที่กำหนดเองตามที่ฉันได้กล่าวไว้ในย่อหน้าสุดท้าย
PM 2Ring

@Tal: ฉันจะเพิ่มตัวอย่าง Python ง่ายๆในคำตอบของฉัน
PM 2Ring

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

-1

นี่คือวิธีที่ฉันไป:

#Replaces a keyword with a long string
#
#This is normally done with sed, but sed
#tries to interpret the string you are
#replacing the keyword with too hard
#
#stdin - contents to look through
#Arg 1 - keyword to replace
#Arg 2 - what to replace keyword with
replace() {
        KEYWORD="$1"
        REPLACEMENT_STRING="$2"

        while IFS= read -r LINE
        do
                if [[ "$LINE" == "$KEYWORD" ]]
                then
                        printf "%s\n" "$REPLACEMENT_STRING"
                else
                        printf "%s\n" "$LINE"
                fi
        done < /dev/stdin
}

มันใช้งานได้ดีในกรณีของฉันเพราะคำหลักของฉันอยู่ในบรรทัดทั้งหมดด้วยตัวเอง หากคำหลักนั้นสอดคล้องกับข้อความอื่น ๆ สิ่งนี้จะไม่ทำงาน

ฉันยังอยากรู้ว่ามีวิธีง่าย ๆ ที่ไม่เกี่ยวข้องกับการเขียนโค้ดโซลูชันของฉันเองหรือไม่


1
หากคุณเป็นกังวลเกี่ยวกับตัวละครพิเศษและความแข็งแกร่งคุณไม่ควรใช้echoเลย ใช้printfแทน และการทำการประมวลผลข้อความใน shell loop เป็นความคิดที่ไม่ดี
ไวด์การ์ด

1
มันจะมีประโยชน์ถ้าคุณพูดถึงในคำถามที่ว่าคำหลักจะเป็นบรรทัดที่สมบูรณ์ FWIW การทุบตีreadค่อนข้างช้า มันมีไว้สำหรับการประมวลผลการป้อนข้อมูลผู้ใช้แบบโต้ตอบไม่ใช่การประมวลผลไฟล์ข้อความ มันช้าเพราะมันอ่าน stdin ถ่านโดยถ่านทำให้ระบบเรียกถ่านแต่ละตัว
PM 2Ring

@ PM 2Ring คำถามของฉันไม่ได้กล่าวถึงคำหลักนั้นอยู่ในแถวของตัวเองเพราะฉันไม่ต้องการคำตอบที่ทำงานได้ในจำนวนที่ จำกัด - ฉันต้องการบางสิ่งที่สามารถทำงานได้อย่างง่ายดายไม่ว่าคำหลักจะอยู่ที่ใด เป็น ฉันยังไม่เคยบอกว่ารหัสของฉันมีประสิทธิภาพ - ถ้ามันเป็นผมจะไม่มองหาทางเลือก ...
Tal

@ Wildcard ยกเว้นว่าฉันทำอะไรหายไปให้พิมพ์ตัวอักษรพิเศษแปลออกมาและอื่น ๆ ที่เกินกว่า 'echo' ที่เป็นค่าเริ่มต้น printf "hi\n"จะทำให้ printf พิมพ์บรรทัดใหม่ในขณะที่echo "hi\n"พิมพ์ตามที่เป็นอยู่
Tal

@Tal, "f" ในprintfย่อมาจาก "format" - อาร์กิวเมนต์แรกที่printfเป็นตัวระบุรูปแบบ หากระบุว่าเป็น%s\nความหมาย "สตริงตามด้วยการขึ้นบรรทัดใหม่" ไม่มีอะไรในการโต้เถียงถัดไปจะถูกตีความหรือแปลโดยตลอดprintf (เชลล์ยังคงสามารถตีความได้แน่นอนให้ดีที่สุดติดมันทั้งหมดในเครื่องหมายคำพูดเดี่ยวถ้าเป็นสตริงตัวอักษรหรือเครื่องหมายคำพูดคู่หากคุณต้องการการขยายตัวของตัวแปร) ดูคำตอบของฉันที่ใช้printfสำหรับรายละเอียดเพิ่มเติม
ไวด์การ์ด
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.