2012-10-30 32 views
5

Tôi đang cố gắng sử dụng awk để phân tích biểu thức nhiều dòng. Một người trong số họ trông giống như sau:kết hợp awk và multilines (sub-regex)

_begin hello world ! 
_attrib0 123 
_attrib1 super duper 
_attrib1 yet another value 
_attrib2 foo 
_end 

Tôi cần trích xuất giá trị được liên kết với _begin và _attrib1. Vì vậy, trong ví dụ, tập lệnh awk phải trả lại (một dòng trên mỗi dòng):

hello world ! super duper yet another value 

Dấu phân tách được sử dụng là ký tự tab. Dấu cách chỉ được sử dụng trong chuỗi.

Trả lời

8

Kịch bản awk sau không được công việc:

#!/usr/bin/awk -f 
BEGIN { FS="\t"; } 
/^_begin/  { output=$2; } 
$1=="_attrib1" { output=output " " $2; } 
/^_end/  { print output; } 

Bạn không nói rõ cho dù bạn muốn có một tab (\t) là đầu ra lĩnh vực phân cách của bạn. Nếu bạn làm thế, hãy cho tôi biết và tôi sẽ cập nhật câu trả lời. (Hoặc bạn có thể, nó là tầm thường.)

Tất nhiên, nếu bạn muốn có một sự thay thế đáng sợ (vì chúng ta đang tiến gần đến Hallowe'en), đây là một giải pháp sử dụng sed:

$ sed -ne '/^_begin./{s///;h;};/^_attrib1[^0-9]/{s///;H;x;s/\n/ /;x;};/^_end/{;g;p;}' input.txt 
hello world ! super duper yet another value 

như thế nào công việc này? Mwaahahaa, tôi rất vui vì bạn đã hỏi.

  • /^_begin./{s///;h;}; - Khi chúng ta thấy _begin, dải nó đi và lưu trữ các phần còn lại của dòng để sed của "giữ đệm".
  • /^_attrib1[^0-9]/{s///;H;x;s/\n/ /;x;}; - Khi chúng ta thấy _attrib1, hãy tách nó ra, gắn nó vào bộ đệm giữ, hoán đổi bộ đệm giữ và không gian mẫu, thay thế dòng mới bằng dấu cách, và hoán đổi bộ đệm giữ và không gian mẫu trở lại.
  • /^_end/{;g;p;} - Chúng tôi đã kết thúc, vì vậy hãy kéo bộ đệm giữ vào vùng mẫu và in.

Giả định rằng trình tách trường nhập của bạn chỉ là một tab.

Rất đơn giản. Ai từng nói sed là arcane ?!

+0

_attrib11 đang thực hiện kịch bản này để thất bại (_attrib1 phù hợp) – malat

+0

Không có '_attrib11' trong các dữ liệu mẫu mà bạn cung cấp. Nếu bạn thích, bạn có thể tạo các điều kiện như '$ 1 ==" _ attrib1 "' thay vì '/^_ attrib1 /' để xử lý, hoặc bạn chỉ có thể để nó như là một regex nhưng kết thúc nó, như '$ 1 ~/^ _ attrib1 $/'. Tôi đề nghị giải pháp thay thế đầu tiên; luôn luôn chọn chuỗi phù hợp đầu tiên, regex (ít nhất) thứ hai. – ghoti

+0

Đã cập nhật câu trả lời của tôi theo yêu cầu mới của bạn. Ngoài ra, bạn cũng có thể thêm một lựa chọn 'sed', cho niềm vui đọc của bạn. – ghoti

1

này nên làm việc:

#!/bin/bash 

awk 'BEGIN {FS="\t"} {if ($1=="_begin" || $1=="_attrib1") { output=output " " $2 }} END{print output}' 
Các vấn đề liên quan