Nếu tôi hiểu chính xác, bạn muốn làm như sau cho mỗi .txt
tệp:
- Xác định vị trí dòng đầu tiên chứa mẫu
text
.
- Trên dòng này, lấy trường được phân tách bằng khoảng trắng thứ hai và ghi nó ra một tệp có tên liên quan đến tệp đầu vào.
Bạn không nói cách xây dựng tên tệp đầu ra. Tôi sẽ làm cho nó giống như các tập tin đầu vào, nhưng kết thúc bằng .out
thay vì .txt
.
Bạn có thể làm điều này với một vòng lặp shell.
for x in *.txt; do
grep 'text' -- "$x" | awk '{print $2; exit}' >"${x%.*}.out"
done
Thoát khỏi awk ngay khi nó hoàn thành công việc của mình nhanh hơn một chút so với việc bảo nó tiếp tục đọc nhưng không làm gì cả. Một khả năng khác là bỏ qua awk hoàn toàn và để phần vỏ thực hiện phân tách dòng (việc này nhanh hơn hay chậm hơn phụ thuộc vào rất nhiều yếu tố mà tôi sẽ không dự đoán nguy hiểm):
for x in *.txt; do
grep 'text' -- "$x" | read -r first second rest && printf '%s\n' "$rest" >"${x%.*}.out"
done
Một cách tiếp cận khác sẽ là làm tất cả công việc trong awk. Awk có thể hoạt động trên nhiều tệp và bạn có thể sử dụng chuyển hướng của awk cho đầu ra. Điều này đòi hỏi phải cắt ít quy trình hơn. Nó khá đơn giản trong Gawk (GNU awk):
awk '/text/ {print $2 >substr(FILENAME, 1, length(FILENAME)-4) ".out"; nextfile}' *.txt
Trong một triển khai awk không có nextfile
, bạn cần xử lý chuyển đổi thủ công sang tệp tiếp theo, điều này làm cho cách tiếp cận này kém hấp dẫn hơn (cả phức tạp hơn và kém hiệu quả hơn).
awk '
FNR==1 {first=1}
first && /text/ {print $2 >substr(FILENAME, 1, length(FILENAME)-4) ".out"; first=0}' *.txt
.txt
thư mục đó..như nó sẽ hoạt động nếu bạn chỉ quan tâm đến các.txt
tệp..Nếu không, có lẽ bạn nên đưa ra một ví dụ hoàn chỉnh ..