【问题标题】:Writing a shell wrapper script for awk为 awk 编写一个 shell 包装脚本
【发布时间】:2010-01-10 13:14:45
【问题描述】:

我想在 shell 脚本中嵌入一个 awk 脚本,但这样做有困难,因为我不知道用 ; 结束语句的位置哪里没有。

这是我的脚本

#!/bin/sh

awk='

BEGIN {FS = ",?+" }

# removes all backspaces preceded by any char except _
function format() {
    gsub("[^_]\b", "")
}

function getOptions() {
    getline
    format() 

    print
}

{
    format()

    if ($0 ~ /^SYNOPSIS$/ {
        getOptions()
        next            
    }

    if ($0  /^[ \t]+--?[A-Za-z0-9]+/) {
        print $0
    }
}

END { print "\n" }'

path='/usr/share/man/man1'
list=$(ls $path)

for item in $list
do
    echo "Command: $item"
    zcat $path$item | nroff -man | awk "$awk"
done > opts

顺便说一句,我正在使用 nawk。

提前致谢

【问题讨论】:

  • 抱歉在这里造成了很多混乱^^...首先,我发布了错误的脚本版本,现在已更正...其次,脚本现在可以工作了:- )...原因是我忘记将 $awk 放在双引号中,这总是在脚本的第一行给我一个语法错误...
  • 谢谢大家的回答,他们提供了很好的见解^^

标签: shell awk


【解决方案1】:

据我所知,有几处错误:

  1. 您没有关闭分配给$awk 的多行字符串。您需要在END { ... } 后面加上单引号
  2. 您似乎实际上并没有在任何地方使用 $awk。也许您的意思是在 do 循环中调用 awk。
  3. 一旦你解决了这些问题,awk 通常对分号相当宽容,但在这方面的任何问题都与在 shell 脚本中使用它无关。

【讨论】:

    【解决方案2】:

    这三行:

    path='/usr/share/man/man1'
    
    list=$(ls $path)
    
    for item in $list
    

    需要改成:

    path='/usr/share/man/man1'
    
    for item in $path/*
    

    如果文件名中有空格并且ls 不打算以这种方式使用。

    【讨论】:

    • 在这个好的改变之后,$path$item 应该只是$item。而且,应该引用变量扩展。所以,zcat "$item" | nroff -man | awk "$awk"
    【解决方案3】:

    我不太确定你的意思,但如果我理解正确,你的 showOpts.awk 就是脚本开头的 awk 代码,所以你可以这样做

    path='/usr/share/man/man1'
    list=$(ls $path)
    
    for item in $list
    do
        echo "Command: $item"
        zcat $path$item | nroff -man | nawk ' BEGIN {FS = ",?+" }
    # removes all backspaces preceded by any char except _
    function format() {
        gsub("[^_]\b", "")
    }
    
    function getOptions() {
        getline
        format()
    
        print
    }
    
    {
        format()
    
        if ($0 ~ /^SYNOPSIS$/ {
            getOptions()
            next
        }
    
        if ($0  /^[ \t]+--?[A-Za-z0-9]+/) {
            print $0
        }
    }
    
    END { print "\n" } '
    done >> opts
    

    你应该使用 >> 而不是 > 。

    【讨论】:

    • 我建议像这样将文字 awk 程序嵌入到循环中会使整个 shell 脚本非常难以阅读。首先将它分配给一个变量(就像 OP 试图做的那样)然后调用 awk "$awk" 更具可读性。
    • 由于重定向在循环之外,没有理由必须是附加的。
    猜你喜欢
    • 2012-02-23
    • 1970-01-01
    • 2020-07-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-23
    • 2012-12-29
    • 1970-01-01
    相关资源
    最近更新 更多