Tôi có "Tôi yêu Suzi và Marry" và tôi muốn đổi "Suzi" thành "Sara".
#!/bin/bash
firstString="I love Suzi and Marry"
secondString="Sara"
# do something...
Kết quả phải như thế này:
firstString="I love Sara and Marry"
Tôi có "Tôi yêu Suzi và Marry" và tôi muốn đổi "Suzi" thành "Sara".
#!/bin/bash
firstString="I love Suzi and Marry"
secondString="Sara"
# do something...
Kết quả phải như thế này:
firstString="I love Sara and Marry"
Câu trả lời:
Để thay thế lần xuất hiện đầu tiên của mẫu bằng một chuỗi đã cho, hãy sử dụng :${parameter/pattern/string}
#!/bin/bash
firstString="I love Suzi and Marry"
secondString="Sara"
echo "${firstString/Suzi/$secondString}"
# prints 'I love Sara and Marry'
Để thay thế tất cả các lần xuất hiện, sử dụng :${parameter//pattern/string}
message='The secret code is 12345'
echo "${message//[0-9]/X}"
# prints 'The secret code is XXXXX'
(Điều này được ghi chép lại trong các hướng dẫn sử dụng Bash Reference , §3.5.3 "Shell Parameter Expansion" .)
Lưu ý rằng tính năng này không được chỉ định bởi POSIX - đó là phần mở rộng Bash - vì vậy không phải tất cả các shell Unix đều thực hiện nó. Để biết tài liệu POSIX có liên quan, hãy xem Thông số kỹ thuật cơ sở tiêu chuẩn kỹ thuật của nhóm mở, Số 7 , khối lượng Shell & Tiện ích , §2.6.2 "Mở rộng tham số" .
\n
trong bối cảnh đó sẽ đại diện cho chính nó, không phải là một dòng mới. Tôi không có Bash tiện dụng ngay bây giờ để kiểm tra, nhưng bạn sẽ có thể viết một cái gì đó như , $STRING="${STRING/$'\n'/<br />}"
. (Mặc dù bạn có thể muốn STRING//
- thay thế tất cả - thay vì chỉ STRING/
.)
echo ${my string foo/foo/bar}
. Bạn cầninput="my string foo"; echo ${input/foo/bar}
//
trực tiếp, nó đề cập đến những gì xảy ra "Nếu mẫu bắt đầu bằng ' /
'" (điều này thậm chí không chính xác, vì phần còn lại của câu đó cho rằng phần bổ sung /
không thực sự là một phần của mô hình) - nhưng tôi không biết nguồn nào tốt hơn.
Điều này có thể được thực hiện hoàn toàn với thao tác chuỗi bash:
first="I love Suzy and Mary"
second="Sara"
first=${first/Suzy/$second}
Điều đó sẽ chỉ thay thế sự xuất hiện đầu tiên; để thay thế tất cả, nhân đôi dấu gạch chéo đầu tiên:
first="Suzy, Suzy, Suzy"
second="Sara"
first=${first//Suzy/$second}
# first is now "Sara, Sara, Sara"
Đối với Dash tất cả các bài viết trước không hoạt động
sh
Giải pháp tương thích POSIX là:
result=$(echo "$firstString" | sed "s/Suzi/$secondString/")
result=$(echo $firstString | sed "s/Suzi/$secondString/g")
echo
đối số. Nó hoạt động một cách khôn ngoan mà không cần trích dẫn với các chuỗi đơn giản, nhưng dễ dàng phá vỡ bất kỳ chuỗi đầu vào không cần thiết nào (khoảng cách không đều, siêu ký tự shell, v.v.).
thử cái này:
sed "s/Suzi/$secondString/g" <<<"$firstString"
Sử dụng bash tốt hơn sed
nếu các chuỗi có các ký tự RegExp.
echo ${first_string/Suzi/$second_string}
Nó có thể di động tới Windows và hoạt động với ít nhất là cũ như Bash 3.1.
Để cho thấy bạn không cần phải lo lắng nhiều về việc trốn thoát, hãy biến điều này:
/home/name/foo/bar
Vào đây:
~/foo/bar
Nhưng chỉ khi /home/name
là trong đầu. Chúng tôi không cần sed
!
Cho rằng bash cho chúng ta các biến ma thuật $PWD
và $HOME
, chúng ta có thể:
echo "${PWD/#$HOME/\~}"
BIÊN TẬP: Cảm ơn Mark Haferkamp trong các bình luận cho ghi chú về trích dẫn / thoát ~
. *
Lưu ý cách biến $HOME
chứa dấu gạch chéo nhưng điều này không phá vỡ bất cứ điều gì.
Đọc thêm: Hướng dẫn Bash-Scripting nâng cao .
Nếu sử dụng sed
là bắt buộc, hãy chắc chắn để thoát khỏi mọi nhân vật .
sed
với pwd
lệnh để tránh xác định một biến mới mỗi lần tùy chỉnh của tôi $PS1
chạy. Bash có cung cấp một cách tổng quát hơn các biến ma thuật để sử dụng đầu ra của lệnh để thay thế chuỗi không? Đối với mã của bạn, tôi phải thoát khỏi ~
để ngăn Bash mở rộng nó thành $ HOME. Ngoài ra, #
trong lệnh của bạn làm gì?
~
": chú ý cách tôi trích dẫn công cụ. Hãy nhớ luôn luôn trích dẫn công cụ! Và điều này không chỉ hoạt động đối với các biến ma thuật: bất kỳ biến nào cũng có khả năng thay thế, nhận được độ dài chuỗi và hơn thế nữa, trong bash. Chúc mừng bạn đã cố gắng $PS1
nhanh: bạn cũng có thể quan tâm $PROMPT_COMMAND
nếu bạn cảm thấy thoải mái hơn trong ngôn ngữ lập trình khác và muốn mã hóa lời nhắc được biên dịch.
echo "${PWD/#$HOME/~}"
không thay thế tôi $HOME
bằng ~
. Thay thế ~
bằng \~
hoặc '~'
làm việc. Bất kỳ trong số này làm việc trên Bash 4.2.53 trên một bản phân phối khác. Bạn có thể vui lòng cập nhật bài viết của bạn để trích dẫn hoặc thoát khỏi ~
để tương thích tốt hơn? Điều tôi muốn nói với câu hỏi "biến ma thuật" của tôi là: Tôi có thể sử dụng thay thế biến của Bash trên, ví dụ, đầu ra của uname
mà không lưu nó làm biến trước không? Đối với cá nhân tôi $PROMPT_COMMAND
, nó phức tạp .
Nếu ngày mai bạn quyết định không yêu Marry thì cô ấy cũng có thể được thay thế:
today=$(</tmp/lovers.txt)
tomorrow="${today//Suzi/Sara}"
echo "${tomorrow//Marry/Jesica}" > /tmp/lovers.txt
Phải có 50 cách để rời xa người yêu của bạn.
Vì tôi không thể thêm một bình luận. @ruaka Để làm cho ví dụ dễ đọc hơn, hãy viết nó như thế này
full_string="I love Suzy and Mary"
search_string="Suzy"
replace_string="Sara"
my_string=${full_string/$search_string/$replace_string}
or
my_string=${full_string/Suzy/Sarah}
Phương pháp vỏ POSIX thuần túy , không giống như câu trả lời dựa trên cơ sở của Roman Kazanovskyised
không cần công cụ bên ngoài, chỉ cần mở rộng tham số riêng của trình bao . Lưu ý rằng tên tệp dài được thu nhỏ để mã phù hợp hơn trên một dòng:
f="I love Suzi and Marry"
s=Sara
t=Suzi
[ "${f%$t*}" != "$f" ] && f="${f%$t*}$s${f#*$t}"
echo "$f"
Đầu ra:
I love Sara and Marry
Làm thế nào nó hoạt động:
Loại bỏ mô hình Suffix nhỏ nhất. "${f%$t*}"
trả về " I love
" nếu hậu tố $t
" Suzi*
" nằm trong $f
" ". I love
Suzi and Marry
Nhưng nếu t=Zelda
, sau đó "${f%$t*}"
xóa không có gì và trả về toàn bộ chuỗi " I love Suzi and Marry
".
Này được sử dụng để kiểm tra nếu $t
là ở $f
với [ "${f%$t*}" != "$f" ]
đó sẽ đánh giá để đúng nếu $f
chuỗi chứa " Suzi*
" và sai nếu không muốn nói.
Nếu kiểm tra trả về giá trị true , hãy xây dựng chuỗi mong muốn bằng cách sử dụng Loại bỏ mẫu nhỏ nhất ${f%$t*}
" I love
" và Loại bỏ mẫu tiền tố nhỏ nhất ${f#*$t}
" and Marry
", với chuỗi thứ 2$s
" Sara
" ở giữa.
Tôi biết điều này đã cũ nhưng vì không ai đề cập đến việc sử dụng awk:
firstString="I love Suzi and Marry"
echo $firstString | awk '{gsub("Suzi","Sara"); print}'
echo [string] | sed "s/[original]/[target]/g"