Làm cách nào để sử dụng sed để xóa tất cả các dòng trong tệp văn bản có chứa một chuỗi cụ thể?
Làm cách nào để sử dụng sed để xóa tất cả các dòng trong tệp văn bản có chứa một chuỗi cụ thể?
Câu trả lời:
Để xóa dòng và in đầu ra ra tiêu chuẩn:
sed '/pattern to match/d' ./infile
Để trực tiếp sửa đổi tệp - không hoạt động với BSD sed:
sed -i '/pattern to match/d' ./infile
Tương tự, nhưng đối với BSD sed (Mac OS X và FreeBSD) - không hoạt động với GNU sed:
sed -i '' '/pattern to match/d' ./infile
Để trực tiếp sửa đổi tệp (và tạo bản sao lưu) - hoạt động với BSD và GNU sed:
sed -i.bak '/pattern to match/d' ./infile
sed '/pattern to match/d' ./infile > ./newfile
hoặc nếu bạn muốn thực hiện chỉnh sửa tại chỗ thì bạn có thể thêm -i
cờ vào sed như trong sed -i '/pattern to match/d' ./infile
. Lưu ý rằng -i
cờ yêu cầu GNU sed và không thể di động
sed -i.backup '/pattern to match/d' ./infile
) Điều đó đã giúp tôi vượt qua các chỉnh sửa tại chỗ.
sed
đối với bất kỳ tệp nào không được kiểm soát phiên bản.
sed -i '' '/pattern/d' ./infile
.
Có nhiều cách khác để xóa các dòng với chuỗi cụ thể bên cạnh sed
:
awk '!/pattern/' file > temp && mv temp file
ruby -i.bak -ne 'print if not /test/' file
perl -ni.bak -e "print unless /pattern/" file
while read -r line
do
[[ ! $line =~ pattern ]] && echo "$line"
done <file > o
mv o file
grep -v "pattern" file > temp && mv temp file
Và tất nhiên sed
(in ngược lại nhanh hơn xóa thực tế):
sed -n '/pattern/!p' file
sed
ví dụ có một hành vi khác nhau, nó chỉ greps! nó phải được cái gì đó như sed -n -i '/pattern/!p' file
.
grep -v "pattern" file > temp; mv temp file
Điều này có thể áp dụng cho một số ví dụ khác tùy thuộc vào giá trị trả về.
seq -f %f 10000000 >foo.txt
. sed d: time sed -i '' '/6543210/d' foo.txt
thực 0m9.294s. sed! p: time sed -i '' -n '/6543210/!p' foo.txt
thực 0m13.671s. (Đối với các tệp nhỏ hơn, sự khác biệt là lớn hơn.)
Bạn có thể sử dụng sed để thay thế các dòng tại chỗ trong một tập tin. Tuy nhiên, dường như chậm hơn nhiều so với việc sử dụng grep cho nghịch đảo thành tệp thứ hai và sau đó di chuyển tệp thứ hai so với tệp gốc.
ví dụ
sed -i '/pattern/d' filename
hoặc là
grep -v "pattern" filename > filename2; mv filename2 filename
Lệnh đầu tiên mất 3 lần lâu hơn trên máy của tôi.
sed '/pattern/d' filename > filename2; mv filename2 filename
Cách dễ dàng để làm điều đó, với GNU sed
:
sed --in-place '/some string here/d' yourfile
-r
tùy chọn (hoặc -E
, tùy thuộc vào phiên bản của bạn). Điều này cho phép việc sử dụng các metacharacters regex +
, ?
, {...}
và (...)
.
Bạn có thể cân nhắc sử dụng ex
(là trình soạn thảo dựa trên lệnh Unix tiêu chuẩn):
ex +g/match/d -cwq file
Ở đâu:
+
thực thi lệnh Ex ( man ex
), giống như -c
thực thi wq
(ghi và thoát)g/match/d
- Lệnh Ex để xóa các dòng đã cho match
, xem: Sức mạnh của gVí dụ trên là một phương pháp tuân thủ POSIX để chỉnh sửa tại chỗ một tệp theo bài đăng này tại các thông số kỹ thuật của ex
Unix.SE và POSIX cho .
Sự khác biệt với sed
là:
sed
là một S tream ED itor, không phải là một trình soạn thảo tập tin. BashFAQ
Trừ khi bạn thích mã không thể truy cập, I / O trên đầu và một số tác dụng phụ xấu khác. Vì vậy, về cơ bản một số tham số (chẳng hạn như tại chỗ / -i
) là các tiện ích mở rộng FreeBSD không chuẩn và có thể không khả dụng trên các hệ điều hành khác.
man ex
nó mang lại cho tôi những người đàn ông cho vim
, có vẻ như ex
là một phần của vim ... nếu tôi hiểu đúng điều đó có nghĩa cú pháp mẫu cho match
là vimregex.com mà là tương tự nhưng khác nhau để POSIX và PCRE hương vị?
Tôi đã vật lộn với điều này trên Mac. Thêm vào đó, tôi cần phải làm điều đó bằng cách sử dụng thay thế biến.
Vì vậy, tôi đã sử dụng:
sed -i '' "/$pattern/d" $file
đâu $file
là tập tin cần xóa và $pattern
là mẫu cần khớp để xóa.
Tôi chọn ''
từ nhận xét này .
Điều cần lưu ý ở đây là sử dụng dấu ngoặc kép trong "/$pattern/d"
. Biến sẽ không hoạt động khi chúng tôi sử dụng dấu ngoặc đơn.
sed
yêu cầu một tham số sau -i
, vì vậy nếu bạn không muốn sao lưu, bạn vẫn phải thêm một chuỗi trống:-i ''
sed -i "/$pattern/d" $file
. Cảm ơn bạn vì câu trả lời.
Tôi đã tạo một điểm chuẩn nhỏ với một tệp chứa khoảng 345 000 dòng. Cách với grep
dường như nhanh hơn khoảng 15 lần so với sed
phương pháp trong trường hợp này.
Tôi đã thử cả có và không có cài đặt LC_ALL = C, có vẻ như không thay đổi đáng kể thời gian. Chuỗi tìm kiếm (CDGA_00004.pdbqt.gz.tar) nằm ở đâu đó ở giữa tệp.
Dưới đây là các lệnh và thời gian:
time sed -i "/CDGA_00004.pdbqt.gz.tar/d" /tmp/input.txt
real 0m0.711s
user 0m0.179s
sys 0m0.530s
time perl -ni -e 'print unless /CDGA_00004.pdbqt.gz.tar/' /tmp/input.txt
real 0m0.105s
user 0m0.088s
sys 0m0.016s
time (grep -v CDGA_00004.pdbqt.gz.tar /tmp/input.txt > /tmp/input.tmp; mv /tmp/input.tmp /tmp/input.txt )
real 0m0.046s
user 0m0.014s
sys 0m0.019s
Bạn cũng có thể sử dụng điều này:
grep -v 'pattern' filename
Ở đây -v
sẽ chỉ in khác với mẫu của bạn (có nghĩa là đảo ngược khớp).
SED:
GIẢI THƯỞNG:
LỚN:
perl -i -nle'/regexp/||print' file1 file2 file3
perl -i.bk -nle'/regexp/||print' file1 file2 file3
Lệnh đầu tiên chỉnh sửa (các) tệp tại chỗ (-i).
Lệnh thứ hai thực hiện tương tự nhưng giữ một bản sao hoặc sao lưu (các) tệp gốc bằng cách thêm .bk vào tên tệp (.bk có thể được thay đổi thành bất kỳ thứ gì).
Chỉ trong trường hợp ai đó muốn làm điều đó cho các chuỗi chính xác, bạn có thể sử dụng -w
cờ trong grep - w cho toàn bộ. Đó là, ví dụ nếu bạn muốn xóa các dòng có số 11, nhưng giữ các dòng có số 111:
-bash-4.1$ head file
1
11
111
-bash-4.1$ grep -v "11" file
1
-bash-4.1$ grep -w -v "11" file
1
111
Nó cũng hoạt động với -f
cờ nếu bạn muốn loại trừ một số mẫu chính xác cùng một lúc. Nếu "danh sách đen" là một tệp có nhiều mẫu trên mỗi dòng mà bạn muốn xóa khỏi "tệp":
grep -w -v -f blacklist file
-w, --word-regexp Select only those lines containing matches that form whole words.
so với-x, --line-regexp Select only those matches that exactly match the whole line. For a regular expression pattern, this is like parenthesizing the pattern and then surrounding it with ^ and $.
cat filename | grep -v "pattern" > filename.1
mv filename.1 filename
để hiển thị văn bản được xử lý trong bảng điều khiển
cat filename | sed '/text to remove/d'
lưu văn bản đã xử lý vào một tập tin
cat filename | sed '/text to remove/d' > newfile
để thêm thông tin văn bản được xử lý một tập tin hiện có
cat filename | sed '/text to remove/d' >> newfile
để xử lý văn bản đã được xử lý, trong trường hợp này, hãy xóa nhiều dòng hơn những gì đã bị xóa
cat filename | sed '/text to remove/d' | sed '/remove this too/d' | more
những | more
sẽ hiển thị văn bản trong khối của một trang tại một thời điểm.
Bạn có thể sử dụng tốt ed
để chỉnh sửa một tệp theo cách tương tự với câu trả lời sử dụng ex
. Sự khác biệt lớn trong trường hợp này là ed
nhận các lệnh của nó thông qua đầu vào tiêu chuẩn, không phải là đối số dòng lệnh như ex
có thể. Khi sử dụng nó trong một tập lệnh, cách thông thường để thực hiện điều này là sử dụng printf
để ra lệnh cho nó:
printf "%s\n" "g/pattern/d" w | ed -s filename
hoặc với một di sản:
ed -s filename <<EOF
g/pattern/d
w
EOF