Tôi có một tệp có tên Element_query
chứa kết quả của một truy vấn:
SQL> select count (*) from element;
[Output of the query which I want to keep in my file]
SQL> spool off;
Tôi muốn xóa dòng thứ 1 và dòng cuối bằng lệnh shell.
Tôi có một tệp có tên Element_query
chứa kết quả của một truy vấn:
SQL> select count (*) from element;
[Output of the query which I want to keep in my file]
SQL> spool off;
Tôi muốn xóa dòng thứ 1 và dòng cuối bằng lệnh shell.
Câu trả lời:
Sử dụng GNU sed
:
sed -i '1d;$d' Element_query
Làm thế nào nó hoạt động :
-i
tùy chọn chỉnh sửa tập tin chính nó. Bạn cũng có thể xóa tùy chọn đó và chuyển hướng đầu ra sang một tệp mới hoặc một lệnh khác nếu bạn muốn.1d
xóa dòng đầu tiên ( 1
chỉ hành động trên dòng đầu tiên, d
để xóa nó)$d
xóa dòng cuối cùng ( $
chỉ hành động trên dòng cuối cùng, d
để xóa nó)Đi xa hơn :
1,5d
sẽ xóa 5 dòng đầu tiên.SQL>
cách sử dụng câu lệnh/^SQL> /d
/^$/d
statement1;statement2;satement3;...
) hoặc bằng cách chỉ định chúng riêng biệt trên dòng lệnh ( -e 'statement1' -e 'statement 2' ...
)1,3d
sẽ xóa ba dòng đầu tiên) nhưng cuối cùng thì khó khăn hơn một chút. Tùy thuộc vào những gì bạn muốn, bạn có thể tốt hơn bằng cách sử dụng điều này: sed -i '/^SQL> /d' Element_query
để xóa các dòng bắt đầu SQL>
bất kể nó nằm ở đâu trong tệp.
sed
lớp lót - sẽ hoạt động để tước số lượng dòng tùy ý từ đầu và đuôi của tệp, Mặc dù vậy, miễn là đầu vào là một tệp thông thường, chỉ để nhóm một đầu vào duy nhất qua hai head
quy trình - đó là cách nhanh nhất để làm điều này thường.
sed -i '1d' table-backup.sql
để xóa dòng đầu tiên của tệp văn bản sql
{ head -n[num] >/dev/null
head -n[num]
} <infile >outfile
Với phần trên, bạn có thể chỉ định số dòng đầu tiên để loại bỏ phần đầu của đầu ra w / head
lệnh đầu tiên và số dòng để ghi vào outfile
phần thứ hai. Nó cũng thường sẽ làm điều này nhanh hơn sed
- đặc biệt là khi đầu vào lớn - mặc dù yêu cầu hai lệnh. Trong trường hợp sed
chắc chắn nên được ưa chuộng hơn, mặc dù là trong trường hợp đó <infile
là không thường xuyên, lseekable tập tin - bởi vì điều này sẽ thường không làm việc như dự định trong trường hợp đó, nhưng sed
có thể xử lý tất cả những thay đổi đầu ra trong một quá trình duy nhất, kịch bản.
Với GNU, head
bạn cũng có thể sử dụng -
dạng phủ định cho [num]
lệnh thứ hai. Trong trường hợp đó, lệnh sau sẽ loại bỏ các dòng đầu tiên và cuối cùng khỏi đầu vào:
{ head -n1 >/dev/null
head -n-1
} <infile >outfile
sed
:Ví dụ, tôi đã đọc một đầu vào gồm 20 dòng và tôi muốn loại bỏ 3 dòng đầu tiên và 7 dòng cuối cùng. Nếu tôi quyết tâm làm như vậy sed
, tôi sẽ làm điều đó với bộ đệm đuôi. Trước tiên tôi sẽ cộng ba và bảy với tổng số dải là mười và sau đó làm:
seq 20 | sed -ne:n -e '3d;N;1,10bn' -eP\;D
Đó là một ví dụ loại bỏ 3 dòng đầu tiên và 7 dòng cuối cùng từ đầu vào. Ý tưởng là bạn có thể đệm bao nhiêu dòng mà bạn muốn tách khỏi đuôi đầu vào trong không gian mẫu trên một ngăn xếp nhưng chỉ P
rint cái đầu tiên trong số này cho mỗi dòng được kéo vào.
1,10
sed
P
gợi ý không có gì vì đối với mỗi dòng, nó xếp chồng đầu vào trong không gian mẫu theo từng dòng trong một b
vòng lặp trang trại.sed
ngăn xếp đều bị d
xóa - và vì vậy 3 dòng đầu tiên bị tước khỏi đầu ra trong một cú trượt.sed
đạt đến $
dòng đầu vào cuối cùng và cố gắng kéo vào phần mở rộng, N
nó chạm EOF và dừng xử lý hoàn toàn. Nhưng tại thời điểm đó, không gian mẫu chứa tất cả các dòng 14,20
- không có dòng nào trong số đó chưa được tô màu P
và không bao giờ.sed
P
gợi ý dòng khác chỉ tối đa \n
ewline xuất hiện đầu tiên trong không gian mẫu và D
bỏ qua tương tự trước khi bắt đầu một chu kỳ mới với những gì còn lại - hoặc 6 dòng đầu vào tiếp theo. Dòng thứ 7 được nối lại vào ngăn xếp với N
lệnh ext trong chu kỳ mới.Và do đó, seq
đầu ra của (là 20 dòng được đánh số liên tục) , sed
chỉ in:
4
5
6
7
8
9
10
11
12
13
Điều này trở nên có vấn đề khi số lượng dòng bạn muốn tách khỏi phần đuôi của đầu vào là lớn - vì sed
hiệu suất của nó tỷ lệ thuận với kích thước của không gian mẫu. Tuy nhiên, tuy nhiên, đây là một giải pháp khả thi trong nhiều trường hợp - và POSIX chỉ định một sed
không gian mẫu để xử lý ít nhất 4kb trước khi phá sản.
tail
cũng hỗ trợ tail -n+<num>
cú pháp mở rộng có nghĩa là "bắt đầu từ dòng <num>
"
Tôi sẽ không trả lời làm thế nào để xóa một số dòng. Tôi sẽ tấn công vấn đề theo cách này:
grep -v '#SQL>' Element_query >outfile
Thay vì đếm các dòng, nó loại bỏ các lệnh SQL bằng cách nhận ra các lời nhắc. Giải pháp này sau đó có thể được tổng quát hóa cho các tệp đầu ra khác của các phiên SQL với nhiều lệnh hơn chỉ hai.
ed
là 'trình soạn thảo văn bản tiêu chuẩn' và nên có sẵn trên các hệ thống không có GNU sed
. Ban đầu nó được thiết kế như một trình soạn thảo văn bản, nhưng nó rất phù hợp với kịch bản.
printf '%s\n' 1d '$d' w q | ed Element_query
1d
xóa dòng đầu tiên của tệp, $d
(trích dẫn để shell không nghĩ đó là biến) xóa dòng cuối cùng, w
ghi tệp và q
thoát ed
. printf
ở đây được sử dụng để định dạng các lệnh cho ed
- mỗi lệnh được theo sau bởi một dòng mới; Tất nhiên có nhiều cách khác để thực hiện điều này.
Có một số cách để loại bỏ (các) dòng hàng đầu và cuối từ một tệp.
Bạn có thể sử dụng awk
vì nó xử lý cả khớp mẫu và đếm dòng,
#you need to know length to skip last line, assume we have 100 lines
awk 'NR>1 && NR<100 {print $0};' < inputfile
#or
awk '/SQL/ {next}; {print $0;};' < inputfile |awk 'NR>1&& NR<10 {print $0};'
Bạn có thể sử dụng grep -v
để loại trừ các dòng bạn không muốn theo mẫu và bạn có thể khớp nhiều mẫu bằng -E
tùy chọn này,
grep -v -E "SQL>" < inputfile > outputfile
Bạn có thể sử dụng head
và tail
cắt bớt số lượng dòng cụ thể,
lines=$((`wc -l < inputfile`-2)) #how many lines in file, less 2
head -n-1 < inputfile | head -n$lines > outputfile
#or
tail -n+2 < inputfile | head -n$lines > outputfile
Bạn có thể sử dụng vi/vim
và xóa (các) dòng đầu tiên và cuối cùng,
vi inputfile
:1
dd
:$
dd
:w! outputfile
:x
bạn có thể sử dụng tập lệnh perl, bỏ qua dòng đầu tiên, lưu từng dòng, in khi bạn nhận được một dòng tiếp theo,
#left as exercise for the reader :-)
head
bạn thực sự không cần đường ống, và trên thực tế, tốt hơn hết là không nên sử dụng nó nếu bạn có thể thoát khỏi nó. Khi bạn thực hiện head | head
- trong khi hai quy trình có thể chạy đồng thời, cả hai đều xử lý thực tế tất cả các dữ liệu giống nhau. Nếu bạn làm thay vì { head >dump; head >save; } <in
bạn chỉ bỏ qua bằng cách bù - dòng đầu tiên đọc 10 dòng ra >dump
và dòng thứ hai đọc 10 dòng tiếp theo>save
.
Bạn sẽ được phục vụ tốt hơn nhiều bằng cách cắt bỏ các lệnh SQL. Bạn có thể làm điều này theo hai cách:
Nếu bạn hoàn toàn chắc chắn rằng chuỗi " SQL>
" không xảy ra ở bất kỳ nơi nào khác trong đầu ra,
grep -v -F 'SQL> ' < infile > outfile
Nếu bạn không chắc chắn,
grep -v '^SQL> .*;$' < infile > outfile
Phiên bản thứ hai chậm hơn nhưng chính xác hơn: nó sẽ bỏ qua các dòng chính xác bắt đầu bằng "SQL>" và kết thúc bằng dấu chấm phẩy, dường như mô tả các dòng bạn muốn loại bỏ.
Tuy nhiên, tốt hơn hết là không đặt đầu ra thêm đó vào tệp để bắt đầu. Hầu hết các hệ thống SQL có một số cách để làm điều đó. Tôi không nói quá nhiều với Oracle, nhưng có lẽ câu trả lời này có thể hữu ích.
Bạn có thể chọn các dòng giữa một phạm vi trong awk
(điều này giả sử bạn biết có bao nhiêu dòng):
awk 'NR>1 && NR < 3' file
Hoặc trong Perl:
perl -ne 'print if $.>1 && $.<3' file
Nếu bạn không biết có bao nhiêu dòng, bạn có thể tính toán nó một cách nhanh chóng bằng cách sử dụng grep
(lưu ý rằng điều này sẽ không tính các dòng trống, hãy sử dụng grep -c '' file
để đếm chúng):
awk -vm="$(grep -c . file2.txt)" 'NR>1 && NR<m' file2.txt
Hãy thử giải pháp này:
tail -n +2 name_of_file | head -n-1
Tùy biến
Bạn có thể dễ dàng thích ứng với nó để xóa các dòng n đầu tiên thay đổi +2
của tail
;
hoặc để xóa các dòng n cuối cùng thay đổi -1
của head
.
Sử dụng awk
:
< inputfile awk 'NR>1 {print r}; {r=$0}' > outputfile
< inputfile
: Chuyển hướng nội dung của inputfile
để awk
'sstdin
> outputfile
: Chuyển hướng nội dung của awk
's stdout
đểoutputfile
NR>1
: chỉ thực hiện các hành động sau nếu số lượng bản ghi đang được xử lý lớn hơn 1{print r}
: in nội dung của biến r
{r=$0}
: gán nội dung của bản ghi đang được xử lý cho biến r
Vì vậy, ở lần thực thi đầu tiên của awk
tập lệnh, khối hành động đầu tiên không được thực thi, trong khi khối hành động thứ hai được thực thi và nội dung của bản ghi được gán cho biến r
; ở lần thực hiện thứ hai, khối hành động đầu tiên được thực thi và nội dung của biến r
được in (do đó bản ghi trước được in); Điều này có tác dụng in từng dòng được xử lý nhưng dòng đầu tiên và dòng cuối cùng.
r
.