Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/jsp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux 如何使用awk提取带引号的字段?_Linux_Bash_Scripting_Awk - Fatal编程技术网

Linux 如何使用awk提取带引号的字段?

Linux 如何使用awk提取带引号的字段?,linux,bash,scripting,awk,Linux,Bash,Scripting,Awk,我正在使用 awk '{ printf "%s", $3 }' 从空格分隔的行中提取某些字段。当然,当这个字段被引用时,我会得到部分结果。有谁能提出一个解决办法吗?这其实很难。我提出了以下awk脚本,它手动拆分行并将所有字段存储在一个数组中 { s = $0 i = 0 split("", a) while ((m = match(s, /"[^"]*"/)) > 0) { # Add all unquoted fields before

我正在使用

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

从空格分隔的行中提取某些字段。当然,当这个字段被引用时,我会得到部分结果。有谁能提出一个解决办法吗?

这其实很难。我提出了以下
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]
}
{
s=$0
i=0
拆分(“,a)
而((m=match(s,/“[^”]*”/)>0){
#在此字段之前添加所有未加引号的字段
n=拆分(子字符串(s,1,m-1),t)
对于(j=1;j=3)#一旦有了字段3,我们就可以停止
打破
}
#处理最后一个带引号的字段之后剩余的未带引号的字段
n=分割(s,t)

对于(j=1;j下次显示输入文件和所需输出。要获取带引号的字段

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

$ awk -F'"' '{for(i=2;i<=NF;i+=2) print $i}' file
field 3
field5
$cat文件
字段1字段2“字段3”字段4“字段5”

$awk-F''''''''{for(i=2;i这里有一个可能的解决方案。它的工作原理是找到以引号开头或结尾的字段,然后将它们连接在一起。最后它会更新字段和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;
    }
}
它产生:

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

字段1:>>>>东西>“更多东西”>“东西”>“更多东西”如果您只是在寻找一个特定的字段,那么

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

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

有效。它将文件按“,所以上面示例中的第二个字段就是您想要的。

显示您的输入文件格式..和您想要的输出!实际上它是apache web服务器日志。似乎awk不能轻松做到这一点。@mmonem那么这可能很有用:这是一个非常复杂的解决方案。如果没有简单的单行解决方案,我会选择perl。”
$ cat file
field1 field2 "field 3" field4 "field5"

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