Tôi có một tệp có tên Element_querychứ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_querychứ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 :
-itù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.1dxóa dòng đầu tiên ( 1chỉ hành động trên dòng đầu tiên, dđể xóa nó)$dxó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,5dsẽ xóa 5 dòng đầu tiên.SQL>cách sử dụng câu lệnh/^SQL> /d/^$/dstatement1;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,3dsẽ 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.
sedlớ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 headquy 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 / headlệnh đầu tiên và số dòng để ghi vào outfilephầ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 sedchắc chắn nên được ưa chuộng hơn, mặc dù là trong trường hợp đó <infilelà 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 sedcó 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, headbạ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ỉ Print cái đầu tiên trong số này cho mỗi dòng được kéo vào.
1,10 sed Pgợ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 bvòng lặp trang trại.sedngăn xếp đều bị dxó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, Nnó 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 Pvà không bao giờ.sed Pgợi ý dòng khác chỉ tối đa \newline xuất hiện đầu tiên trong không gian mẫu và Dbỏ 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 Nlệ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) , sedchỉ 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ì sedhiệ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 sedkhông gian mẫu để xử lý ít nhất 4kb trước khi phá sản.
tailcũ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.
edlà '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
1dxó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, wghi tệp và qthoá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 awkvì 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 -Etùy chọn này,
grep -v -E "SQL>" < inputfile > outputfile
Bạn có thể sử dụng headvà tailcắ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/vimvà 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 :-)
headbạ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; } <inbạn chỉ bỏ qua bằng cách bù - dòng đầu tiên đọc 10 dòng ra >dumpvà 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 > outfileNếu bạn không chắc chắn,
grep -v '^SQL> .*;$' < infile > outfilePhiê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 +2của tail;
hoặc để xóa các dòng n cuối cùng thay đổi -1củ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đểoutputfileNR>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 rVì vậy, ở lần thực thi đầu tiên của awktậ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.