Thay thế một số ký tự trong một chuỗi bằng một ký tự khác


278

Tôi có một chuỗi như AxxBCyyyDEFzzLMN và tôi muốn thay thế tất cả các lần xuất hiện của x , yz bằng _ .

Làm thế nào tôi có thể đạt được điều này?

Tôi biết điều đó echo "$string" | tr 'x' '_' | tr 'y' '_'sẽ làm việc, nhưng tôi muốn làm điều đó trong một lần, mà không cần sử dụng đường ống.


Bạn có muốn thay thế bất kỳ chuỗi x, y hoặc z liên tiếp nào bằng một dấu gạch dưới hoặc bạn muốn thay thế từng x, y hoặc z bằng một dấu gạch dưới? Ngoài ra, những gì về trình tự hỗn hợp, như thế AxyzBnào? Ba dấu gạch dưới hay một?
David Z

tr '[xyz]'sẽ thay thế [], quá. Đối số chỉ đơn giản là một danh sách các ký tự (mặc dù phạm vi như thế a-zlà ổn và trong một số triển khai, các lớp ký tự POSIX như [:digit:]).
tripleee

Câu trả lời:


327
echo "$string" | tr xyz _

sẽ thay thế từng xảy ra x, yhoặc zvới _, cho A__BC___DEF__LMNtrong ví dụ của bạn.

echo "$string" | sed -r 's/[xyz]+/_/g'

sẽ thay thế các lần lặp lại của x, yhoặc zvới một lần duy nhất _, đưa ra A_BC_DEF_LMNtrong ví dụ của bạn.


19
Trên Mac, tôi đã nhận được các tùy chọn sau: sed: tùy chọn bất hợp pháp - r sử dụng: sed script [-Ealn] [-i extension] [file ...] sed [-Ealn] [-i extension] [-e script]. .. [-f script_file] ... [file ...]
catanore

Tôi có một chuỗi chứa các ,[]{}()~ký tự. Tôi muốn thay thế nó bằng từng nhân vật đặc biệt đã trốn thoát bằng '\'cách nào tôi có thể thực hiện việc này bằng oneshot?
inckka

2
@halakala Mac xuất xưởng với phiên bản sed hơi khác. Xem câu hỏi này: unix.stackexchange.com/questions/13711/ Liệu Thay vào đó, bạn có thể cài đặt "gnu-sed" với trình quản lý gói Homebrew sau đó sử dụng gsedtệp nhị phân: $ brew install gnu-sedsau đó$ gsed -r 's/[xyz]+/_/g'
John Kary

6
Trên * BSD (và do đó, OSX), sed -E(về cơ bản) tương đương với sed -rnhiều bản phân phối Linux, Nếu bạn sử dụng, sed 's/[xyz][xyz]*/_/g'bạn không cần tùy chọn này. Tất nhiên, điều này tương đương với tr -s xyz _vì vậy không có nhu cầu thực sự sedở đây.
tripleee

@inckka Bạn không thể sử dụng trcho điều đó. sed 's/[][{}()~,]/\\&/g'nhưng thực sự, hãy hỏi một câu hỏi mới nếu bạn có câu hỏi tiếp theo (dĩ nhiên hãy liên kết lại ở đây để tham khảo). Ngẫu nhiên, ,~không phải là metacharacters regex (mặc dù ~được mở rộng để $HOMEở một số vị trí bằng cách Bash và một số tiện ích khác; không shtuy nhiên).
tripleee

285

Sử dụng mở rộng tham số Bash :

orig="AxxBCyyyDEFzzLMN"
mod=${orig//[xyz]/_}

7
Thay thế xấu
Alexey

1
@Alexey, ví dụ của tôi hoạt động với tôi (bash 4.3.11 (1) -release). Hãy chắc chắn rằng bạn đang sử dụng bash. Các vỏ khác có thể không hoạt động (mặc dù một số sẽ).
Matthew Flaschen

Cảm ơn bạn @MatthewFlaschen. Đây chính xác là những gì tôi cần để thực hiện thay thế sed cho một đường dẫn tuyệt đối trong tập lệnh bash (thay thế / bằng \ / vì vậy sed chấp nhận nó).
Ryan G

1
@RyanG tại sao sử dụng sednếu bash có tích hợp thay thế?
MestreLion

@MestreLion Điều đó có thể đã sai, nhưng tôi cần thay thế một tên biến tiêu chuẩn trong một loạt các tệp bằng một đường dẫn tuyệt đối, mà tôi đã sử dụng thay thế sed inplace. nhưng bạn không thể có "/" mà không thoát nó trong lệnh. Tôi đã xâu chuỗi các hoạt động với nhau trong bash. Đây sẽ không phải là cách tốt nhất để thao tác một chuỗi trong bash?
Ryan G

111

Bạn có thể thấy liên kết này hữu ích:

http://tldp.org/LDP/abs/html/opes-manipulation.html

Nói chung,

Để thay thế trận đấu đầu tiên của chuỗi con $ bằng thay thế $:

${string/substring/replacement}

Để thay thế tất cả các kết quả của chuỗi con $ bằng thay thế $:

${string//substring/replacement}

EDIT: Lưu ý rằng điều này áp dụng cho một biến có tên $ chuỗi.


16
Lưu ý rằng điều này hoạt động trên một biến có tên "chuỗi" không phải trên chuỗi chữ.
mattdm

1
hữu ích nhất, vì nó chứa tài liệu tham khảo.
Os3

Giải pháp tốt nhất và ngắn nhất.
Northtree

8
read filename ;
sed -i 's/letter/newletter/g' "$filename" #letter

^ sử dụng bao nhiêu trong số này nếu bạn cần và bạn có thể tạo mã hóa BASIC của riêng mình


5

Đây là một giải pháp với việc mở rộng tham số shell thay thế nhiều lần xuất hiện liền kề bằng một lần duy nhất _:

$ var=AxxBCyyyDEFzzLMN
$ echo "${var//+([xyz])/_}"
A_BC_DEF_LMN

Lưu ý rằng mẫu yêu cầu khớp mẫu mở rộng, được bật bằng+(pattern)

shopt -s extglob

Ngoài ra, với -stùy chọn ("bóp") của tr:

$ tr -s xyz _ <<< "$var"
A_BC_DEF_LMN
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.