Awk - xuất dòng thứ hai của một số tệp .dat thành một tệp


9

Tôi có nhiều tệp giống như: (trong thực tế tôi có 80)

file1.dat

2 5

6 9

7 1

file2.dat

3 7

8 4

1 3

Tôi muốn kết thúc với một tập tin chứa tất cả các dòng thứ hai. I E

đầu ra.dat

6 9

8 4

Những gì tôi có cho đến nay các vòng lặp mặc dù tên tập tin nhưng sau đó ghi đè lên tập tin trước nó. ví dụ: đầu ra của các tệp trên sẽ chỉ là

8 4

kịch bản shell của tôi trông như thế này:

bài viết

TEND = 80

TINDX = 0

while [ $TINDX - lt $TEND]; do

awk '{ print NR==2 "input-$TINDX.dat > output.dat

TINDX = $((TINDX+1))

done

Câu trả lời:


17

Hủy bỏ whilevòng lặp và sử dụng mở rộng nẹp vỏ và cũng FNRlà một awkbiến tích hợp:

awk 'FNR==2{print $0 > "output.dat"}' file{1..80}.dat

9
thậm chí ngắn hơnawk 'FNR==2' file{1..80}.dat > output.dat
Archemar

7

Thế còn ... head -n 2 input.dat | tail -n 1 | awk...


Có, head/ tailchắc chắn là một lựa chọn, awksau đó bạn không cần .
jimmij

7

sed sẽ là đủ:

sed -sn 2p file{1..80}.dat > output.dat

-s tùy chọn là cần thiết để in dòng thứ 2 từ mỗi tệp, nếu không thì chỉ có dòng thứ 2 của tệp đầu tiên sẽ được in.


2

sedgiải pháp của araga là tốt nhất, vâng. Nhưng tôi vì tôi thích head|tailcắt một chút , có một head|tailgiải pháp hỗ trợ nhiều tệp chứ không chỉ một tệp input.dat. Sử dụng vòng lặp for, thay vì chuyển danh sách các tệp sang sed, cũng giúp bạn dễ dàng thực hiện các thao tác khác với tệp trước / sau khi trích xuất dòng thứ hai bằng sed.

# empty output.dat first
rm output.dat

# have a one-liner
for file in *.dat; do head -2 $file | tail -1 >> output.dat; done 

Phiên bản đa dòng nhận xét:

NB: mã dưới đây sẽ chạy. Chúng tôi có thể tự do đặt một linebreak sau một |, &&hoặc ||, và tiếp tục chỉ huy của chúng tôi trên dòng tiếp theo; chúng tôi thậm chí có thể đặt ý kiến ​​ở giữa. Tôi đã dành nhiều năm không biết điều này (và không thực sự nhìn thấy nó ở bất cứ đâu). Kiểu này ít hữu ích hơn tại dấu nhắc tương tác, nhưng dọn sạch các tệp script không có kết thúc.

# empty output.dat first
rm output.dat

for file in *.dat; do
    # file -> lines 1 and 2 of file
    head -2 $file |
    # lines 1 and 2 of file -> line 2 of file >> appended to output.dat
    tail -1 >> output.dat
done

0

Rõ ràng có rất nhiều cách để làm điều này - tôi nghĩ rằng tôi thích câu trả lời của @ aragaer sed nhất .

Đây là một trong đó sử dụng các phần mềm bash hoàn toàn và không cần rẽ nhánh bất kỳ tiện ích bên ngoài nào:

for f in file{1..80}.dat; do
    { read && read && printf "%s\n" "$REPLY"; } < "$f"
done > output.dat

0

Để sử dụng hiệu quả awksedtrong các câu trả lời ở đây trên nhiều tệp, tốt hơn nên sử dụng nextfilecâu lệnh để bỏ qua việc xử lý các dòng không mong muốn trong awk.

awk 'FNR==2{ print >"output.dat"; nextfile}' infile{1..80}.dat

và với sed, chúng ta có thể thoát khi xử lý trên dòng thứ 3 và sedsẽ xử lý tệp tiếp theo.

sed -sn '2p;3q' infile{1..80}.dat > output.dat
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.