Làm thế nào để xóa mỗi dòng thứ hai từ một tập tin?


25

Tập tin:

Data inserted into table. Total count 13
No error occurred
Data inserted into table. Total count 45
No error occurred
Data inserted into table. Total count 14
No error occurred
Data inserted into table. Total count 90
No error occurred

Tập tin đầu ra dự kiến:

Data inserted into table. Total count 13
Data inserted into table. Total count 45
Data inserted into table. Total count 14
Data inserted into table. Total count 90

Tôi muốn đầu ra nhìn theo cách này: mỗi dòng thứ hai sẽ bị xóa nhưng sẽ không có khoảng cách giữa các dòng.


5
Bạn có muốn xóa mọi dòng thứ hai hoặc tất cả các dòng có chứa "Không có lỗi xảy ra" không? Điều gì xảy ra nếu hai dòng liên tiếp có "Không có lỗi xảy ra" ?
Tulains Córdova 04/08/2015

1
@ user1598390 Tôi nghĩ rằng ... trong trường hợp grep -v "No error occurred" fileđó lệnh này sẽ hoạt động ... những gì @paul đã trả lời. Trong tệp đầu ra, sẽ không có dòng nào chứa "Không có lỗi xảy ra" phần này.
pmaipmui

1
Sau đó, tiêu đề của câu hỏi là sai lệch.
Tulains Córdova

Câu trả lời:


36

Với sed:

sed -e n\;d <file

Với POSIX awk:

awk 'FNR%2' <file

Nếu bạn có tuổi awk(thích oawk), bạn cần:

oawk 'NR%2 == 1' <file

Với ex:

$ ex file <<\EX
:g/$/+d
:wq!
EX

sẽ chỉnh sửa tập tin tại chỗ.

  • g đánh dấu một lệnh toàn cầu
  • /$/ phù hợp với mọi dòng
  • +d xóa dòng tiếp theo
  • wq! lưu tất cả các thay đổi

Cách tiếp cận này có chung lý tưởng với sedcách tiếp cận, xóa mọi dòng tiếp theo của dòng hiện tại bắt đầu từ dòng 1.

Với perl:

perl -ne 'print if $. % 2' <file

perl6:

perl6 -ne '.say if $*IN.ins % 2' <file
perl6 -ne '.say if ++$ % 2' <file

Vâng ... nó hoạt động ... :) ... cái đầu tiên đang hoạt động .... tôi cũng đã thử cái thứ hai .. nó nói `awk: cú pháp lỗi dòng1 awk: bails out gần dòng 1 '
pmaipmui

sed -en \; d <file ~ Có hoạt động của nó @cuonglm ...
pmaipmui

1
Tôi đoán rằng bạn đã sử dụng n\;dthay vì 'n;d'lưu một ký tự quý giá nhưng logic đó sẽ biến mất khỏi cửa sổ khi bạn không cần thiết sử dụng công -etắc và chuyển hướng tệp <!
Tom Fenech

1
@Geek: Đây chỉ là phiên bản ngắn hơn sed -e 'n;d', giúp bạn tiết kiệm một ký tự.
cuonglm

1
@Geek: nlệnh ghi không gian mẫu vào đầu ra tiêu chuẩn nếu -nđược sử dụng, sau đó thay thế không gian mẫu bằng dòng tiếp theo. Đây là mỗi dòng lẻ sẽ được in bằng n, ngay cả dòng sau đó đọc vào không gian mẫu nhưng xóa ngay lập tức bằng dlệnh`.
cuonglm

62

Việc giải quyết điều này bằng cách xóa mọi dòng thứ hai có thể dễ bị lỗi (ví dụ: khi quá trình đôi khi tạo ra hai dòng có ý nghĩa thay vì một dòng). Có thể tốt hơn để lọc rác:

grep -v "No error occurred" file

Nó có thể chạy dưới dạng bộ lọc, bạn có thể thêm nhiều mẫu rác ở đây và cải thiện kết quả.


9
+1 để chỉ ra rằng đôi khi dòng thứ hai là quan trọng!
Kaz Wolfe

12

Tham gia câu hỏi, với GNU sed:

sed '0~2d' file

sẽ xóa từng dòng thứ hai nhưng tôi muốn cung cấp các dòng bộ lọc theo nội dung:

sed '/Data/! d' file

hoặc có cùng kết quả

sed '/No error/d' file

tệp sed '/ Không có lỗi / d' ~ cho đầu ra mong muốn @Costas
pmaipmui

5
Lưu ý rằng hai cách cuối cùng là cách viết phức tạp grep Datagrep -v 'No error'
Stéphane Chazelas

5

Đây là một cách sử dụng sed:

sed -n 'p;n' filename

Một cách khác với GNU sed:

sed -n '1~2p' filename

Đầu ra từ các lệnh trên:

Data inserted into table. Total count 13
Data inserted into table. Total count 45
Data inserted into table. Total count 14
Data inserted into table. Total count 90

Ý bạn là gì khi nói shortest way using sed?
cuonglm

Lý do trong glệnh là gì? sed -n 'p;n'Là đủ.
Costas

@cuonglm: Ý tôi là nói cách làm đơn giản. Bằng cách loại bỏ từ đó. :)
serenesat

@Costas: Cảm ơn! Chỉ cần kiểm tra, nó hoạt động mà không có g. loại bỏ g khỏi lệnh. :)
serenesat

4

Bạn có thể thử với awk:

awk 'NR % 2 != 0' file

hoặc bạn chỉ có thể in các dòng chứa Data inserted:

awk '$0 ~ /Data inserted/' file

Tôi đã thử cả hai câu trả lời của bạn và cả hai đều hoạt động ... :)
pmaipmui

3

Một câu trả lời khác, bạn có thể sử dụng vi / vim!

qdjddq

Và sau đó nếu tệp của bạn là 500 dòng (ví dụ)

250 @ d

Và sau đó để viết và thoát loại

: x

Hoặc nếu có lỗi xảy ra và bạn không muốn lưu:

: q!

Giải trình:

q      #Start Recording
 d     #Put the recording into register 'd'
  j    #Move the cursor down
   dd  #Delete the line
     q #Stop recording


250    #Number of repeats
   @d  #Playback the recording in register 'd'.

2

Đây là một cách làm khác nhau:

< file paste - - | cut -f1

Điều này giả định rằng các dòng số lẻ không chứa các tab. Nếu họ làm như vậy, thì bạn sẽ cần chọn một ký tự phân cách khác, ví dụ :ở đây:

< file paste -d: - - | cut -d: -f1

1
Tôi đã nghĩ đến điều này khi lần đầu tiên nhìn thấy câu hỏi ... Thật thú vị khi thực hiện bài kiểm tra tốc độ sedvới một tệp khổng lồ (ví dụ: 20 triệu dòng). Dù sao, +1 nhưng thực sự, để tránh đau đầu, hãy chọn một dấu phân cách không có khả năng xảy ra trong tệp văn bản, như $'\002'...
don_crissti

@don_crissti có sử dụng ký tự không in cho dấu phân cách là một ý tưởng hay. Và vâng, điều này nhanh hơn so với giải pháp sed. Tôi đã tạo một tập tin thử nghiệm với seq 100000000 > 100mil.txt. Các paste|cutgiải pháp hoàn thành trong khoảng 7,5 giây, so với gần 12 cho sedgiải pháp. Có vẻ như được lặp lại. greplà nhanh nhất mặc dù. Ubuntu 14.04 với các công cụ GNU tiêu chuẩn.
Chấn thương kỹ thuật số

Đúng, paste+ cutđược tối ưu hóa rất nhiều cho công việc của họ, vì vậy, không có gì ngạc nhiên khi sự kết hợp của họ khá nhanh chóng ...
don_crissti

1

Một lựa chọn khác (ngắn hơn)

sed 'n; d' file

3
Nó dài hơn của tôi sed n\;d, thêm -echỉ là thói quen của tôi.
cuonglm

0

Nó cũng giải quyết vấn đề, mặc dù chậm hơn một chút:

vim -c "%normal jdd" -c "wq" file
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.