2010-08-11 3 views
6

Я используюКак использовать awk для извлечения цитируемого поля?

awk '{ printf "%s", $3 }' 

извлечь некоторую область из пространства разделителями строки. Конечно, я получаю частичные результаты, когда поле цитируется с свободными пространствами внутри. Может ли любой орган предложить решение, пожалуйста?

+0

показать ваш формат входного файла .. и ваш желаемый результат! – ghostdog74

ответ

1

Это на самом деле довольно сложно. Я придумал следующий сценарий awk, который разбивает строку вручную и сохраняет все поля в массиве.

{ 
    s = $0 
    i = 0 
    split("", a) 
    while ((m = match(s, /"[^"]*"/)) > 0) { 
     # Add all unquoted fields before this field 
     n = split(substr(s, 1, m - 1), t) 
     for (j = 1; j <= n; j++) 
      a[++i] = t[j] 
     # Add this quoted field 
     a[++i] = substr(s, RSTART + 1, RLENGTH - 2) 
     s = substr(s, RSTART + RLENGTH) 
     if (i >= 3) # We can stop once we have field 3 
      break 
    } 
    # Process the remaining unquoted fields after the last quoted field 
    n = split(s, t) 
    for (j = 1; j <= n; j++) 
     a[++i] = t[j] 
    print a[3] 
} 
+0

Это довольно сложное решение. Если нет простого * одного line * solution, я бы пошел на perl – mmonem

6

показать ваш входной файл и желаемый результат в следующий раз. Чтобы получить котируемые поля,

$ cat file 
field1 field2 "field 3" field4 "field5" 

$ awk -F'"' '{for(i=2;i<=NF;i+=2) print $i}' file 
field 3 
field5 
+0

На самом деле это журнал веб-сервера apache. Кажется, что awk не может сделать это легко. – mmonem

+1

@mmonem Тогда это может быть полезно: http://serverfault.com/questions/ 11028/у-вас-есть-любой-полезный-AWK-и-Grep-скрипты-для-разбора-Apache-журналы – schot

1

Возможное альтернативное решение этой проблемы. Он работает путем поиска полей, которые начинаются или заканчиваются кавычками, а затем объединяются вместе. В конце он обновляет поля и NF, поэтому, если вы поместите больше паттернов после того, как происходит слияние, вы можете обрабатывать (новые) поля, используя все обычные функции awk.

Я думаю, что это использует только функции POSIX awk и не полагается на расширения gawk, но я не совсем уверен.

# This function joins the fields $start to $stop together with FS, shifting 
# subsequent fields down and updating NF. 
# 
function merge_fields(start, stop) { 
    #printf "Merge fields $%d to $%d\n", start, stop; 
    if (start >= stop) 
     return; 
    merged = ""; 
    for (i = start; i <= stop; i++) { 
     if (merged) 
      merged = merged OFS $i; 
     else 
      merged = $i; 
    } 
    $start = merged; 

    offs = stop - start; 
    for (i = start + 1; i <= NF; i++) { 
     #printf "$%d = $%d\n", i, i+offs; 
     $i = $(i + offs); 
    } 
    NF -= offs; 
} 

# Merge quoted fields together. 
{ 
    start = stop = 0; 
    for (i = 1; i <= NF; i++) { 
     if (match($i, /^"/)) 
      start = i; 
     if (match($i, /"$/)) 
      stop = i; 
     if (start && stop && stop > start) { 
      merge_fields(start, stop); 
      # Start again from the beginning. 
      i = 0; 
      start = stop = 0; 
     } 
    } 
} 

# This rule executes after the one above. It sees the fields after merging. 
{ 
    for (i = 1; i <= NF; i++) { 
     printf "Field %d: >>>%s<<<\n", i, $i; 
    } 
} 

На входном файле, как:

thing "more things" "thing" "more things and stuff" 

он производит:

Field 1: >>>thing<<< 
Field 2: >>>"more things"<<< 
Field 3: >>>"thing"<<< 
Field 4: >>>"more things and stuff"<<< 
0

Если вы просто ищете для конкретного поля, то

$ cat file 
field1 field2 "field 3" field4 "field5" 

awk -F"\"" '{print $2}' file 

работы. Он разбивает файл на «, поэтому второе поле в приведенном выше примере является тем, которое вы хотите.

Смежные вопросы