แทนที่หนึ่งอักขระด้วยอักขระอื่นใน Bash


223

ฉันต้องสามารถทำได้คือแทนที่ช่องว่าง ( ) ด้วยจุด ( .) ในสตริงในทุบตี

ฉันคิดว่ามันจะค่อนข้างง่าย แต่ฉันใหม่ดังนั้นฉันจึงไม่สามารถหาวิธีแก้ไขตัวอย่างที่คล้ายกันสำหรับการใช้งานนี้

คำตอบ:


390

ใช้การแทนที่สตริง inline shell ตัวอย่าง:

foo="  "

# replace first blank only
bar=${foo/ /.}

# replace all blanks
bar=${foo// /.}

ดูhttp://tldp.org/LDP/abs/html/string-manipulation.htmlสำหรับรายละเอียดเพิ่มเติม


1
ในขณะที่การแก้ปัญหานี้ดีเมื่อจัดการกับสตริงสั้น ๆ (ในกรณีทั่วไปฉันเดา) หนึ่งอาจชอบtrสำหรับสตริงยาว ในระบบของฉันมีtrประสิทธิภาพดีกว่าทุบตีเริ่มต้นที่สตริงที่มีมากกว่า1000ตัวอักษร ดูเหมือนว่าความซับซ้อนของเวลาของ bash นั้นแย่กว่าเชิงเส้น x="$(tr -dc 'a-z \n' </dev/urandom | head -c1M)"; time y="$(tr ' ' \\- <<< "$x")"; time z="${x// /-}"การทดสอบขนาดเล็ก: ที่มีความยาวสตริงของ 1M (= 2 ^ 20) trเข้ามา0.04sและทุบตี 5.0.11 17sเอา ด้วย 2M trใช้เวลา0.07s(คาดว่า) แต่ทุบตีใช้เวลา69s(4 ครั้งนานเป็นสองเท่าของความยาวสตริง)
Socowi

@Socowi การเล่นกับ 1Mb ที่เก็บไว้ในตัวแปรนั้นไม่ใช่เรื่องปกติ! เกินกว่า 10Kb ดูเหมือนว่าทุบตีจะเร็วกว่าการตีtr... !
F. Hauri

สำหรับอักขระที่หลบหนีเช่นบรรทัดใหม่ตรวจสอบให้แน่ใจว่าได้ค้นหา$'\n'
user2561747

75

คุณสามารถใช้trแบบนี้:

tr " " .

ตัวอย่าง:

# echo "hello world" | tr " " .
hello.world

จากman tr:

DESCRIPTION
     แปลบีบและ / หรือลบตัวอักษรจากอินพุตมาตรฐานเขียนไปยังเอาต์พุตมาตรฐาน


ในขณะที่มันใช้งานได้กับคำถามตามที่ถาม แต่มันก็น้อยกว่าคำตอบที่ยอมรับได้ (ซึ่งใช้ได้กับการแทนที่ตัวอักษรและสตริงโดยพลการ) และมันยังเกี่ยวข้องกับและคำสั่งภายนอก
Dan Dascalescu

2
ในทางกลับกันมันทำงานกับไฟล์ 2gb โดยไม่ต้องโหลดทุกสิ่งลงในหน่วยความจำ
aioobe

คำถามเกี่ยวกับ "สตริงในทุบตี" ไม่ใช่ไฟล์ขนาดใหญ่โดยพลการ
Dan Dascalescu

52

ใน bash คุณสามารถทำการแทนที่รูปแบบในสตริงด้วยการ${VARIABLE//PATTERN/REPLACEMENT}สร้าง ใช้เพียง/และไม่//แทนที่เฉพาะเหตุการณ์แรกเท่านั้น รูปแบบเป็นรูปแบบสัญลักษณ์แทนเช่นไฟล์คลำ

string='foo bar qux'
one="${string/ /.}"     # sets one to 'foo.bar qux'
all="${string// /.}"    # sets all to 'foo.bar.qux'



4

ลองใช้เส้นทางนี้:

echo \"hello world\"|sed 's/ /+/g'|sed 's/+/\/g'|sed 's/\"//g'

มันจะแทนที่ช่องว่างภายในสตริงที่มีเครื่องหมายคำพูดคู่+และแทนที่ด้วย+เครื่องหมายคำพูดคู่เครื่องหมายด้วยแบ็กสแลชจากนั้นลบ / แทนที่เครื่องหมายคำพูดคู่

ฉันต้องใช้สิ่งนี้เพื่อแทนที่ช่องว่างในหนึ่งในเส้นทางของฉันใน Cygwin

echo \"$(cygpath -u $JAVA_HOME)\"|sed 's/ /+/g'|sed 's/+/\\/g'|sed 's/\"//g'

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