trích xuất từ ​​dòng này sang dòng khác và sau đó lưu vào tệp riêng biệt


7

Tôi đã thử vận ​​may của mình grepsednhưng bằng cách nào đó tôi không quản lý để làm cho đúng.

Tôi có một tệp nhật ký có kích thước khoảng 8 GB. Tôi cần phân tích khoảng thời gian 15 phút của hoạt động đáng ngờ. Tôi định vị một phần của tệp nhật ký mà tôi cần xem và tôi đang cố trích xuất các dòng đó và lưu nó vào một tệp riêng. Làm thế nào tôi có thể làm điều đó trên một máy CentOS thông thường?

Lần thử cuối cùng của tôi là thế nhưng nó không hoạt động. Tôi thua lỗ khi nói đến sedvà những loại lệnh đó.

sed -n '2762818,2853648w /var/log/output.txt' /var/log/logfile

Câu trả lời:


9
sed -n '2762818,2853648p' /var/log/logfile > /var/log/output.txt

p là để in


Cảm ơn. Có cách nào để nói sedđể tạo một tệp mới nếu không tồn tại? Ngay bây giờ tôi đang nhận được sed: can't read /var/log/output.txt: No such file or directory. Tất nhiên tôi chỉ có thể tạo một tập tin, nhưng để học hỏi, tôi muốn biết làm thế nào để tự động làm nó.
koljanep

Lệnh này sẽ tạo tập tin /var/log/logfiletự động nếu không tồn tại. Nó thậm chí sẽ thay thế nó nếu nó đã tồn tại. Vấn đề là: /var/log/logfilelà tập tin sẽ có các dòng bạn muốn. Bây giờ, tệp bạn muốn đọc/var/log/output.txt: Tôi vừa sao chép ví dụ của bạn. Có vẻ như bạn đang cố đọc từ một tệp không tồn tại. Bạn nên thay thế nó bằng đường dẫn thực tế nơi tệp nhật ký bạn muốn đọc.
thiagowfx

1
Ops, bạn đúng. Tôi không bận tâm đọc tên của các tập tin, tôi chỉ giả sử cái bên trái là đầu vào và cái bên phải là đầu ra. Tôi sẽ cập nhật câu trả lời của tôi.
thiagowfx

2

Có lẽ cách tốt nhất để làm điều này là với chuyển hướng vỏ, như những người khác đã đề cập. sedmặc dù, trong khi yêu thích cá nhân, có lẽ sẽ không làm điều này hiệu quả hơn ý muốn head- được thiết kế để chỉ lấy quá nhiều dòng từ một tệp.

Có những câu trả lời khác trên trang web này cho thấy rõ ràng rằng đối với các tệp lớn head -n[num] | tail -n[num]sẽ vượt trội hơn sedmọi lúc, nhưng có lẽ còn nhanh hơn thế nữa là tránh hoàn toàn đường ống.

Tôi đã tạo một tệp như:

echo | dd cbs=5000000 conv=block | tr \  \\n >/tmp/5mil_lines

Và tôi đã chạy nó qua:

{ head -n "$((ignore=2762817))" >&2
  head -n "$((2853648-ignore))" 
} </tmp/5mil_lines 2>/dev/null  |
sed -n '1p;$p'                

Tôi chỉ sử dụng sedtất cả ở đó để chỉ lấy dòng đầu tiên và cuối cùng để hiển thị cho bạn ...

2762818
2853648

Điều này hoạt động bởi vì khi bạn nhóm các lệnh với { ... ; }và chuyển hướng đầu vào cho nhóm giống như ... ; } <inputtất cả chúng sẽ chia sẻ cùng một đầu vào. Hầu hết các lệnh sẽ làm cạn kiệt toàn bộ infile trong khi đọc nó, vì vậy trong một { cmd1 ; cmd2; } <infiletrường hợp thường cmd1đọc từ đầu của infile đến đuôi của nó và cmd2không có gì cả.

head, tuy nhiên, sẽ luôn luôn chỉ tìm kiếm cho đến nay thông qua sự vô dụng của nó như được hướng dẫn để làm, và vì vậy trong một ...

{ head -n [num] >/dev/null
  head -n [num]
} <infile 

... trong trường hợp người đầu tiên tìm kiếm [num]và bỏ kết quả đầu ra của nó /dev/nullvà lần thứ hai còn lại để bắt đầu đọc nơi đầu tiên rời khỏi nó.

Bạn có thể làm...

{ head -n "$((ignore=2762817))" >/dev/null
  head -n "$((2853648-ignore))" >/path/to/outfile
} <infile

Cấu trúc này cũng hoạt động với các loại lệnh ghép khác. Ví dụ:

set "$((n=2762817))" "$((2853648-n))"
for n do head "-n$n" >&"$#"; shift
done <5mil_lines 2>/dev/null | 
sed -n '1p;$p'

... mà in ...

2762818
2853648

Nhưng nó cũng có thể hoạt động như sau:

d=$(((  n=$(wc -l </tmp/5mil_lines))/43 ))      &&
until   [ "$(((n-=d)>=(!(s=143-n/d))))" -eq 0 ] &&
        head "-n$d" >>"/tmp/${s#1}.split"
do      head "-n$d" > "/tmp/${s#1}.split"       || ! break
done    </tmp/5mil_lines

Trên vỏ ban đầu đặt $n$dcác biến thành ...

  • $n
    • Số dòng được báo cáo bởi wctệp thử nghiệm của tôi/tmp/5mil_lines
  • $d
    • Thương số của $n/4343 chỉ là một số chia được chọn tùy ý.

Sau đó nó vòng untilnó đã giảm đi $nbởi $dmột giá trị ít $d. Trong khi làm như vậy, nó lưu số đếm tách của nó $svà sử dụng giá trị đó trong vòng lặp để tăng >tệp đầu ra được đặt tên được gọi /tmp/[num].split. Kết quả là nó đọc ra một số lượng tương đương các \ntrường được phân tách bằng ewline trong phần lưu trữ của nó thành một tệp dữ liệu mới cho mỗi lần lặp - chia nó ra bằng 43 lần trong suốt vòng lặp. Nó quản lý nó mà không cần phải đọc dữ liệu của nó quá 2 lần - lần đầu tiên là khi wcnó đếm các dòng của nó và trong phần còn lại của hoạt động, nó chỉ đọc nhiều dòng như nó ghi vào outfile mỗi lần.

Sau khi chạy nó, tôi đã kiểm tra kết quả của mình như ...

tail -n1 /tmp/*split | grep .

ĐẦU RA:

==> /tmp/01.split <==
116279  
==> /tmp/02.split <==
232558  
==> /tmp/03.split <==
348837  
==> /tmp/04.split <==
465116  
==> /tmp/05.split <==
581395  
==> /tmp/06.split <==
697674  
==> /tmp/07.split <==
813953  
==> /tmp/08.split <==
930232  
==> /tmp/09.split <==
1046511 
==> /tmp/10.split <==
1162790 
==> /tmp/11.split <==
1279069 
==> /tmp/12.split <==
1395348 
==> /tmp/13.split <==
1511627 
==> /tmp/14.split <==
1627906 
==> /tmp/15.split <==
1744185 
==> /tmp/16.split <==
1860464 
==> /tmp/17.split <==
1976743 
==> /tmp/18.split <==
2093022 
==> /tmp/19.split <==
2209301 
==> /tmp/20.split <==
2325580 
==> /tmp/21.split <==
2441859 
==> /tmp/22.split <==
2558138 
==> /tmp/23.split <==
2674417 
==> /tmp/24.split <==
2790696 
==> /tmp/25.split <==
2906975 
==> /tmp/26.split <==
3023254 
==> /tmp/27.split <==
3139533 
==> /tmp/28.split <==
3255812 
==> /tmp/29.split <==
3372091 
==> /tmp/30.split <==
3488370 
==> /tmp/31.split <==
3604649 
==> /tmp/32.split <==
3720928 
==> /tmp/33.split <==
3837207 
==> /tmp/34.split <==
3953486 
==> /tmp/35.split <==
4069765 
==> /tmp/36.split <==
4186044 
==> /tmp/37.split <==
4302323 
==> /tmp/38.split <==
4418602 
==> /tmp/39.split <==
4534881 
==> /tmp/40.split <==
4651160 
==> /tmp/41.split <==
4767439 
==> /tmp/42.split <==
4883718 
==> /tmp/43.split <==
5000000 

@don_crissti - đợi đã, cái gì? tacsẽ phải ăn toàn bộ tập tin - giống như tail, tôi đoán vậy - nhưng tôi sẽ nghĩ rằng nếu bạn làm headđiều đó trước tiên, bạn sẽ chỉ có thể đảo ngược phần sau của tập tin. Đó không phải là những gì xảy ra? Xin lỗi, điều này chỉ làm tôi ngạc nhiên. Nhưng nhìn vào nó ngày càng nhiều và đó là một khái niệm thú vị.
mikeerv 17/03/2015

@don_crissti - ngày càng thú vị hơn ... Tôi sẽ thử một strace. Đợi một chút - tacphải kiểm tra stdin để kiểm tra đầu vào có thể tìm kiếm và tua lại bộ mô tả - đó là điều duy nhất có ý nghĩa với tôi. Tôi sẽ kiểm tra nó với strace, mặc dù. Điều đó, bằng cách này, sẽ là hành vi xấu, tôi nghĩ.
mikeerv 17/03/2015

@don_crissti - Vâng - đó là hành động lseek(): [pid 6542] lseek(0, 0, SEEK_END) = 551 [pid 6542] ioctl(0, SNDCTL_TMR_TIMEBASE or SNDRV_TIMER_IOCTL_NEXT_DEVICE or TCGETS, 0x7fff51f3a940) = -1 ENOTTY (Inappropriate ioctl for device) [pid 6542] lseek(0, 0, SEEK_END) = 551 [pid 6542] lseek(0, 0, SEEK_SET) = 0- không phải là hành vi xấu, xem xét những gì tacđược cho là phải làm, nhưng bất thường và trái với những gì các tiện ích tiêu chuẩn nên làm.
mikeerv 17/03/2015

@don_crissti - hoàn toàn không.
mikeerv 17/03/2015

Mike, điều này hoàn toàn không liên quan đến câu trả lời của bạn ở đây nhưng tôi chỉ tò mò ... nếu bạn đọc lại câu hỏi, tại sao "lần thử cuối cùng" của OP không hoạt động? Có sedngoài kia không hỗ trợ w? Câu trả lời được chấp nhận thực hiện khá giống nhau chỉ với p>... Không có ý nghĩa gì ...
don_crissti

0

Bạn có thể có thể thực hiện điều này với sự trợ giúp của headtailkết hợp lệnh như dưới đây.

head -n{to_line_number} logfile | tail -n+{from_line_number} > newfile

Thay thế from_line_numberto_line_numbervới số dòng bạn mong muốn.

Kiểm tra

cat logfile
This is first line.
second
Third
fourth
fifth
sixth
seventh
eighth
ninth
tenth

##I use the command as below. I extract from 4th line to 10th line. 

head -n10 logfile | tail -n+4 > newfile
fourth
fifth
sixth
seventh
eighth
ninth
tenth
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.