Câu trả lời:
sed -i 's/original/new/g' file.txt
Giải trình:
sed
= Truyền phát trực tuyến-i
= tại chỗ (nghĩa là lưu lại vào tệp gốc)Chuỗi lệnh:
s
= lệnh thay thếoriginal
= một biểu thức chính quy mô tả từ cần thay thế (hoặc chỉ chính từ đó)new
= văn bản để thay thế nó bằngg
= toàn cầu (nghĩa là thay thế tất cả và không chỉ là lần xuất hiện đầu tiên)file.txt
= tên tệp
sed
sẽ khớp với chúng. Thêm một -r
cờ nếu bạn muốn sử dụng REs mở rộng thay thế.
/
ký tự mà bạn cần khớp, bạn chỉ có thể sử dụng một số ký tự khác làm dấu phân cách (ví dụ 's_old/text_new/text_g'
). Nếu không, bạn có thể đặt \
trước bất kỳ $ * . [ \ ^
để có được ký tự chữ.
sed -i '.bak' 's/original/new/g' file.txt
cũng có thể được chạy với phần mở rộng có độ dài bằng không sed -i '' 's/original/new/g' file.txt
, sẽ không tạo ra bản sao lưu.
Có một số cách khác nhau để làm điều này. Một là sử dụng sed
và Regex. SED là một Trình chỉnh sửa luồng để lọc và chuyển đổi văn bản. Một ví dụ như sau:
marco@imacs-suck: ~$ echo "The slow brown unicorn jumped over the hyper sleeping dog" > orly
marco@imacs-suck: ~$ sed s/slow/quick/ < orly > yarly
marco@imacs-suck: ~$ cat yarly
The quick brown unicorn jumped over the hyper sleeping dog
Một cách khác có thể có ý nghĩa hơn < strin
và > strout
là với đường ống!
marco@imacs-suck: ~$ cat yarly | sed s/unicorn/fox/ | sed s/hyper/lazy/ > nowai
marco@imacs-suck: ~$ cat nowai
The quick brown fox jumped over the lazy sleeping dog
cat
trong cat file | sed '...'
là không cần thiết. Bạn có thể nói trực tiếp sed '...' file
.
sed -i'.bak' -e 's/unicorn/fox/g;s/hyper/brown/g' yarly
sẽ lấy tệp yarly và thực hiện 2 thay đổi tại chỗ trong khi tạo bản sao lưu. Sử dụng time bash -c "$COMMAND"
theo thời gian nó cho thấy phiên bản này nhanh hơn ~ 5 lần.
Có vô số cách để đạt được nó. Tùy thuộc vào mức độ phức tạp của những gì người ta cố gắng đạt được khi thay thế chuỗi và tùy thuộc vào công cụ mà người dùng quen thuộc, một số phương pháp có thể được ưa thích hơn các phương pháp khác.
Trong câu trả lời này, tôi đang sử dụng input.txt
tệp đơn giản , bạn có thể sử dụng để kiểm tra tất cả các ví dụ được cung cấp ở đây. Nội dung tập tin:
roses are red , violets are blue
This is an input.txt and this doesn't rhyme
Bash không thực sự có nghĩa là để xử lý văn bản, nhưng thay thế đơn giản có thể được thực hiện thông qua mở rộng tham số , đặc biệt ở đây chúng ta có thể sử dụng cấu trúc đơn giản ${parameter/old_string/new_string}
.
#!/bin/bash
while IFS= read -r line
do
case "$line" in
*blue*) printf "%s\n" "${line/blue/azure}" ;;
*) printf "%s\n" "$line" ;;
esac
done < input.txt
Tập lệnh nhỏ này không thực hiện thay thế tại chỗ, nghĩa là bạn sẽ phải lưu văn bản mới vào tệp mới và loại bỏ tệp cũ hoặc mv new.txt old.txt
Lưu ý bên lề: nếu bạn tò mò về lý do tại sao while IFS= read -r ; do ... done < input.txt
được sử dụng, về cơ bản, cách đọc từng dòng tệp của shell. Xem cái này để tham khảo.
AWK, là một tiện ích xử lý văn bản, khá thích hợp cho nhiệm vụ đó. Nó có thể thay thế đơn giản và nâng cao hơn nhiều dựa trên các biểu thức thông thường . Nó cung cấp hai chức năng: sub()
và gsub()
. Cái đầu tiên chỉ thay thế lần xuất hiện đầu tiên, trong khi lần thứ hai - thay thế lần xuất hiện trong toàn bộ chuỗi. Chẳng hạn, nếu chúng ta có chuỗi one potato two potato
, đây sẽ là kết quả:
$ echo "one potato two potato" | awk '{gsub(/potato/,"banana")}1'
one banana two banana
$ echo "one potato two potato" | awk '{sub(/potato/,"banana")}1'
one banana two potato
AWK có thể lấy một tệp đầu vào làm đối số, do đó, thực hiện cùng một việc với input.txt
, sẽ dễ dàng:
awk '{sub(/blue/,"azure")}1' input.txt
Tùy thuộc vào phiên bản AWK mà bạn có, nó có thể có hoặc không có chỉnh sửa tại chỗ, do đó, thông lệ là lưu và thay thế văn bản mới. Ví dụ như một cái gì đó như thế này:
awk '{sub(/blue/,"azure")}1' input.txt > temp.txt && mv temp.txt input.txt
Sed là một biên tập viên dòng. Nó cũng sử dụng các biểu thức thông thường, nhưng đối với các thay thế đơn giản, nó đủ để làm:
sed 's/blue/azure/' input.txt
Điều tốt về công cụ này là nó có chỉnh sửa tại chỗ, bạn có thể bật bằng -i
cờ.
Perl là một công cụ khác thường được sử dụng để xử lý văn bản, nhưng nó là ngôn ngữ có mục đích chung và được sử dụng trong mạng, quản trị hệ thống, ứng dụng máy tính để bàn và nhiều nơi khác. Nó đã mượn rất nhiều khái niệm / tính năng từ các ngôn ngữ khác như C, sed, awk và các ngôn ngữ khác. Thay thế đơn giản có thể được thực hiện như vậy:
perl -pe 's/blue/azure/' input.txt
Giống như sed, perl cũng có cờ -i.
Ngôn ngữ này rất linh hoạt và cũng được sử dụng trong rất nhiều ứng dụng. Nó có rất nhiều hàm để làm việc với các chuỗi, trong số đó là replace()
, vì vậy nếu bạn có biến như thế var="Hello World"
, bạn có thể làmvar.replace("Hello","Good Morning")
Cách đơn giản để đọc tệp và thay thế chuỗi trong đó sẽ là như vậy:
python -c "import sys;lines=sys.stdin.read();print lines.replace('blue','azure')" < input.txt
Tuy nhiên, với Python, bạn cũng cần xuất ra tệp mới, bạn cũng có thể thực hiện từ bên trong tập lệnh. Ví dụ, đây là một đơn giản:
#!/usr/bin/env python
import sys
import os
import tempfile
tmp=tempfile.mkstemp()
with open(sys.argv[1]) as fd1, open(tmp[1],'w') as fd2:
for line in fd1:
line = line.replace('blue','azure')
fd2.write(line)
os.rename(tmp[1],sys.argv[1])
Kịch bản lệnh này được gọi với input.txt
đối số dòng lệnh. Lệnh chính xác để chạy tập lệnh python với đối số dòng lệnh sẽ là
$ ./myscript.py input.txt
hoặc là
$ python ./myscript.py input.txt
Tất nhiên, đảm bảo rằng ./myscript.py
trong thư mục làm việc hiện tại của bạn và theo cách đầu tiên, hãy đảm bảo rằng nó được thiết lập có thể thực thi được vớichmod +x ./myscript.py
Python cũng có thể có các biểu thức chính quy, đặc biệt, có re
mô-đun, có re.sub()
chức năng, có thể được sử dụng để thay thế nâng cao hơn.
tr
lệnh trong unix
tr
là một công cụ tuyệt vời, nhưng lưu ý rằng nó là để thay thế bộ ký tự (ví dụ tr abc cde
sẽ dịch a
để c
, b
để d
Nó là một chút khác nhau từ thay thế toàn bộ từ như với. sed
Hoặcpython
Bạn có thể sử dụng Vim trong chế độ Ex:
ex -s -c '%s/OLD/NEW/g|x' file
%
chọn tất cả các dòng
s
thay thế
g
thay thế tất cả các trường hợp trong mỗi dòng
x
viết nếu thay đổi đã được thực hiện (họ có) và thoát
Thông qua lệnh gsub của awk,
awk '{gsub(/pattern/,"replacement")}' file
Thí dụ:
awk '{gsub(/1/,"0");}' file
Trong ví dụ trên, tất cả các số 1 được thay thế bằng 0 bất kể cột nằm ở đâu.
Nếu bạn muốn thay thế trên một cột cụ thể, thì hãy làm như thế này,
awk '{gsub(/pattern/,"replacement",column_number)}' file
Thí dụ:
awk '{gsub(/1/,"0",$1);}' file
Nó chỉ thay thế 1 bằng 0 trên cột đầu tiên.
Thông qua Perl,
$ echo 'foo' | perl -pe 's/foo/bar/g'
bar
inotifywait
thuộc sh
env, và báo cáo dữ liệu ở định dạng CSV (vì định dạng tùy chỉnh là buggy). Sau đó tôi đã tìm ra không có cách đơn giản nào để xử lý tài liệu CSV trong các tập lệnh shell ... Và tôi muốn nó rất nhẹ. Vì vậy, tôi bắt đầu một kịch bản khá đơn giản để phân tích và báo cáo CSV. Tôi đã đọc thông số CSV và nhận thấy nó được xây dựng kỹ lưỡng hơn tôi mong đợi và hỗ trợ giá trị đa dòng được gói trong dấu ngoặc kép. Tôi đã dựa vào sed
mã thông báo nhưng sớm nhận ra rằng ngay cả những gì sed
gọi là đa dòng cũng lên đến hai dòng. Sau đó, nếu một trong các giá trị CSV của tôi trải dài trên hai dòng thì sao?
sed
là s tream ed itor , trong đó bạn có thể sử dụng |
(ống) để gửi con suối chuẩn (STDIN và STDOUT cụ thể) thông qua sed
và thay đổi chúng theo chương trình một cách nhanh chóng, làm cho nó một công cụ hữu ích trong truyền thống triết lý Unix; nhưng cũng có thể chỉnh sửa các tập tin trực tiếp bằng cách sử dụng -i
tham số được đề cập dưới đây.
Hãy xem xét những điều sau đây :
sed -i -e 's/few/asd/g' hello.txt
s/
được sử dụng để s ubstitute biểu thức tìm thấy few
với asd
:
Số ít, những người dũng cảm.
Các asd, dũng cảm.
/g
là viết tắt của "toàn cầu", có nghĩa là làm điều này cho toàn bộ dòng. Nếu bạn rời khỏi /g
(với s/few/asd/
, luôn cần có ba dấu gạch chéo bất kể điều gì) và few
xuất hiện hai lần trên cùng một dòng, chỉ lần đầu tiên few
được thay đổi thành asd
:
Số ít đàn ông, ít phụ nữ, dũng cảm.
Đàn ông asd, ít phụ nữ, dũng cảm.
Điều này hữu ích trong một số trường hợp, như thay đổi các ký tự đặc biệt ở đầu dòng (ví dụ, thay thế các ký hiệu lớn hơn một số người sử dụng để trích dẫn tài liệu trước đó trong các chủ đề email bằng một tab ngang trong khi để lại bất đẳng thức đại số được trích dẫn sau dòng không bị ảnh hưởng), nhưng trong ví dụ của bạn, nơi bạn xác định rằng bất cứ nơi nào few
xảy ra nó nên được thay thế, hãy chắc chắn rằng bạn có điều đó /g
.
Hai tùy chọn (cờ) sau đây được kết hợp thành một , -ie
:
-i
tùy chọn được sử dụng để chỉnh sửa i n đặt trên các tập tin hello.txt
.
-e
tùy chọn này cho biết lệnh e xpression / lệnh chạy, trong trường hợp này s/
.
Lưu ý: Điều quan trọng là bạn sử dụng -i -e
để tìm kiếm / thay thế. Nếu bạn làm như vậy -ie
, bạn tạo một bản sao lưu của mọi tệp có chữ 'e' được thêm vào.
Bạn có thể làm như thế này:
locate <part of filaname to locate> | xargs sed -i -e "s/<Old text>/<new text>/g"
Ví dụ: để thay thế tất cả các lần xuất hiện [logdir ',' '] (không có []) bằng [logdir', os.getcwd ()] trong tất cả các tệp là kết quả của lệnh định vị, hãy:
ex1:
locate tensorboard/program.py | xargs sed -i -e "s/old_text/NewText/g"
ex2:
locate tensorboard/program.py | xargs sed -i -e "s/logdir', ''/logdir', os.getcwd()/g"
trong đó [tenorboard / program.py] là tệp để tìm kiếm
logdir', ''
-> /logdir', os.getcwd()
) làm cho câu trả lời này khó phân tích. Ngoài ra, đáng để xác định rằng câu trả lời của bạn trước tiên định vị các tệp để sử dụng sed, bởi vì đó không phải là một phần của câu hỏi.