Giải pháp chỉ với sed
bản thân sed có thể tạo ra cả dòng chưa sửa đổi và dòng đã sửa đổi:
$ echo "redis::staging::key" | sed 's/^/RENAME /; p; s/staging/development/g'
RENAME redis::staging::key
RENAME redis::development::key
Ở trên, trước tiên sed thêm chuỗi RENAME vào đầu dòng. Sau đó, p
lệnh cho sed in dòng như nó đứng tại thời điểm đó (với "dàn" vẫn còn trong đó). Sự thay thế tiếp theo đặt vào "phát triển" và sau đó phiên bản đó cũng được in.
Cập nhật: Giả sử chúng ta muốn đầu ra trên một dòng:
$ echo "redis::staging::key" | sed 's/.*/RENAME & &/; s/staging/development/2'
RENAME redis::staging::key redis::development::key
s
đầu tiên lệnh trên thêm RENAME vào đầu và sau đó nhân đôi dòng. Điều thứ hai thay thế sự xuất hiện thứ hai của giai đoạn bằng sự phát triển.
Tại sao phiên bản xargs không thay thế?
xargs -I {} echo "RENAME {} $(echo {} | sed 's/staging/development/g')"
Trước khi xargs thực thi, bash xử lý các chuỗi. Đặc biệt, nó thấy $(echo {} | sed 's/staging/development/g')
và nó thực thi nó ("thay thế lệnh") và nhận được kết quả {}
. Vì vậy, khi xargs cuối cùng được chạy, nó sẽ thấy lệnh:
xargs -I {} echo "RENAME {} {}"
Do đó, s/staging/development/g
thay thế không bao giờ được thực hiện.
Làm cho xargs và shell hoạt động cùng nhau theo thứ tự phù hợp
Có một bản sửa lỗi cho điều này:
$ echo "redis::staging::key" | xargs -I {} sh -c 'echo RENAME {} $(echo {} | sed 's/staging/development/g')'
RENAME redis::staging::key redis::development::key
Ở trên đặt các lệnh bash trong dấu ngoặc đơn và chuyển chúng làm đối số cho sh
. Bằng cách này, chuỗi không được xử lý bởi shell cho đến khi xargs thực hiện các thay thế.