我将重复的awk表达式更改为一个函数

时间:2015-07-07 21:00:49

标签: regex bash shell awk

我有8个awk表达式,只有我正在搜索的2种模式不同。所以我然后创建了一个awk函数来改进我的代码,但现在它不会工作。我正在做的是......

printFmt () {
    awk -v MYPATH="$MYPATH" -v FILE_EXT="$FILE_EXT" -v NAME_OF_FILE="$NAME_OF_FILE" -v DATE="$DATE" -v PATTERN="$1" -v SEARCH="$2" '
        $0 ~ PATTERN {
            rec = $1 OFS $2 OFS $4 OFS $7
            for (i=9; i<=NF; i++) {
                rec = rec OFS $i
                if ($i ~ SEARCH) {
                    break
                }
            }
        print rec >> "'$MYPATH''$NAME_OF_FILE''$DATE'.'$FILE_EXT'"
    }
' "$FILE_LOCATION"
}

并使用printFmt "$STORED_PROCS_FINISHED" "/([01])/"致电。我的代码完全在上面,除了SEARCH它是/([01])/。是否有一些我缺少的语法?

2 个答案:

答案 0 :(得分:2)

请阅读Arnold Robbins撰写的有效Awk编程,第4版:

printFmt () {
    awk -v regexp1="$1" -v regexp2="$2" '
        $0 ~ regexp1 {
            rec = $1 OFS $2 OFS $4 OFS $7
            for (i=9; i<=NF; i++) {
                rec = rec OFS $i
                if ($i ~ regexp2) {
                    break
                }
            }
        print rec
    }
' "$FILE_LOCATION" >> "${MYPATH}${NAME_OF_FILE}${DATE}.${FILE_EXT}"
}

printFmt "$STORED_PROCS_FINISHED" "[01]"

您对变量名使用全部大写字母很糟糕 - 仅适用于导出的shell变量。

请勿使用&#34; pattern&#34;因为它含糊不清,而且搜索&#34;没有意义 - 为我命名为regexp1和regexp2的变量提出两个有意义的名称。

答案 1 :(得分:1)

如评论中所述:

  1. 您应该省略作为参数传递的正则表达式的斜杠。传递"([01])"代替"/([01])/"应该可以正常工作。我不相信括号也是必要的;只有"[01]"也应该有用。

  2. 您将-v的值传递给awk脚本中未使用的awk脚本。您有shell使用这些值来创建文件名。您应该不将值传递给awk,或者不应该使用shell来创建文件名。

  3. 鉴于这些评论,我认为您的代码可能是:

    printFmt() {
        awk -v PATTERN="$1" -v SEARCH="$2" '
            $0 ~ PATTERN {
                rec = $1 OFS $2 OFS $4 OFS $7
                for (i=9; i<=NF; i++) {
                    rec = rec OFS $i
                    if ($i ~ SEARCH) {
                        break
                    }
                }
                print rec 
            }
            ' "$FILE_LOCATION" >> "$MYPATH$NAME_OF_FILE$DATE.$FILE_EXT"
    }
    
    printFmt "$STORED_PROCS_FINISHED" "[01]"
    

    除非每次调用函数时构造的文件名都会改变,否则我会在函数外部创建一次文件名,并在函数外部使用它:

    printFmt() {
        awk -v PATTERN="$1" -v SEARCH="$2" '
            $0 ~ PATTERN {
                rec = $1 OFS $2 OFS $4 OFS $7
                for (i=9; i<=NF; i++) {
                    rec = rec OFS $i
                    if ($i ~ SEARCH) {
                        break
                    }
                }
                print rec 
            }
            ' "$FILE_LOCATION"
    }
    
    OUTFILE="$MYPATH$NAME_OF_FILE$DATE.$FILE_EXT"
    
    printFmt "$STORED_PROCS_FINISHED" "[01]" >> "$OUTFILE"
    …7 other calls to printFmt each with I/O redirection…
    

    甚至:

    {
    printFmt "$STORED_PROCS_FINISHED" "[01]"
    …7 other calls to printFmt…
    } >> "$OUTFILE"
    

    总的来说,我可能会将要扫描的文件作为参数传递给函数:

    printFmt() {
        pattern="${1:?}"
        search="${2:?}"
        shift 2
        awk -v PATTERN="$pattern1" -v SEARCH="$search" '
            $0 ~ PATTERN {
                rec = $1 OFS $2 OFS $4 OFS $7
                for (i=9; i<=NF; i++) {
                    rec = rec OFS $i
                    if ($i ~ SEARCH) {
                        break
                    }
                }
                print rec 
            }
            ' "$@"    # All the remaining arguments
    }
    
    {
    printFmt "$STORED_PROCS_FINISHED" "[01]" "$FILE_LOCATION"
    …7 other calls to printFmt…
    } >> "$OUTFILE"
    

    这为数据的来源和转移提供了最大的灵活性。如果没有提供文件名参数,它允许函数读取其标准输入。如果${1:?}未设置为非空字符串,则$1表示法将生成错误;这是检查参数1(模式)是否已提供给函数的粗略但有效的方法。与搜索参数类似。错误消息不会提供非常丰富的信息,但任何消息可能比在未提供值时尝试继续更好。