Trích xuất một phần của các dòng với mẫu cụ thể bằng cách sử dụng awk, sed


18

Tôi có một câu hỏi liên quan đến các nhà khai thác awk / sed. Tôi có một tập tin lớn có các dòng được lặp lại

Expression loweWallrhoPhi :  sum=-6.97168e-09
Expression leftWallrhoPhi :  sum=6.97168e-09
Expression lowerWallPhi :  sum=-5.12623e-12
Expression leftWallPhi :  sum=5.12623e-12
Expression loweWallrhoUSf :  sum=-6.936e-09
Expression leftWallrhoUSf :  sum=6.97169e-09
Expression lowerWallUSf :  sum=-5.1e-12
Expression leftWallUSf :  sum=5.12624e-12

Tôi muốn trích xuất giá trị sau tổng trong từng trường hợp trong tệp riêng biệt. Có thể làm như vậy trong một lần?

Câu trả lời:


26

Với lệnh grep:

grep -oP 'sum=\K.*' inpufile > outputfile

grep với -Pcác tham số (perl-regapi) hỗ trợ \K, sử dụng để bỏ qua các ký tự được so khớp trước đó.

Với lệnh awk:

awk -F"=" '{print $NF}' inputfile > outputfile

Awk NFcung cấp cho bạn tổng số trường trong một bản ghi / dòng. Vì vậy, giá trị cuối cùng của số đó là số trường cuối cùng trong một bản ghi / dòng.

Với lệnh sed:

sed 's/^.*sum=//' inpufile > outputfile

^.*=sumthay thế tất cả các ký tự ( .*) giữa bắt đầu dòng ( ^) và ký tự cuối ( sum=) bằng khoảng trắng char.

Kết quả:

-6.97168e-09
6.97168e-09
-5.12623e-12
5.12623e-12
-6.936e-09
6.97169e-09
-5.1e-12
5.12624e-12

Nếu bạn muốn lưu từng giá trị vào một tệp riêng biệt, hãy sử dụng các lệnh trên vào một vòng lặp while:

while read line; do
    echo "$line" | grep -oP 'sum=\K.*'     > $(echo "$line" |awk '{print $2}');
   #echo "$line" | awk -F"=" '{print $NF}' > $(echo "$line" |awk '{print $2}');
   #echo "#line" | sed 's/^.*sum=//'       > $(echo "$line" |awk '{print $2}');
done < file

Điều đó bao gồm sum=và không giống với giá trị sausum=
Anthon

OP muốn giá trị sau tổng, cũng là mô tả awk của NF là khủng khiếp.

1
Để hoàn thành câu trả lời rất tốt này, bạn cũng có thể sử dụng cut: cut -d'=' -f2 file.
fedorqui

Đây là một câu trả lời rất tốt. Tôi thích nó. Cảm ơn bạn.
Jaffer Wilson

6

Nếu tôi hiểu chính xác câu hỏi bạn muốn chỉ nhận các giá trị sau =và lưu trữ các giá trị này trong các tệp riêng biệt, dựa trên trường thứ hai (?). Nếu tôi đúng hãy thử một cái gì đó như thế này:

$ awk -F'[ =]' '{print $6>"file_"$2".txt"}' file

Kết quả:

$ ls -1
  file_leftWallPhi.txt
  file_leftWallUSf.txt
  file_leftWallrhoPhi.txt
  file_leftWallrhoUSf.txt
  file_loweWallrhoPhi.txt
  file_loweWallrhoUSf.txt
  file_lowerWallPhi.txt
  file_lowerWallUSf.txt

$ cat  file_leftWallPhi.txt
  5.12623e-12

@KasiyA Tôi không thể tái tạo vấn đề của bạn với GNU awk 4.0.2. Lệnh từ câu trả lời của tôi cũng hoạt động với -ctùy chọn (chế độ tương thích với UNIX truyền thống awknơi các phần mở rộng GNU bị tắt). Hãy chắc chắn rằng bạn đã cập nhật tệp đầu vào vì câu hỏi ban đầu đã được chỉnh sửa và các dòng trống đã bị xóa.
jimmij

1

Bạn có thể làm điều đó bằng cách sed

sed -E 's/^.* (\S+)\s*:.*=(\S+)/echo "\2" > "\1".txt/' file | bash

Kịch bản tìm ra hai mảnh trong dòng:

  1. giữa các khoảng trắng và :nên chứa một số (hơn 0) ký hiệu không phải khoảng trắng ;
  2. một số (nhiều hơn 0) ký hiệu không phải không gian sau =;

và định dạng từ lệnh thực thi của nó được chuyển qua đường ống đến bash


Một câu trả lời linh hoạt hơn nhiều.
duanev
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.