无法在Unix Shell脚本中使用grep的-C

无法在Unix Shell脚本中使用grep的-C,unix,scripting,grep,Unix,Scripting,Grep,我能够在正常的命令行中使用grep grep "ABC" Filename -C4 这是给我所需的输出,这是4线以上和以下的匹配模式线 但是,如果在unixshell脚本中使用相同的命令,我将无法grep模式上下的行。它给我的输出是模式匹配的唯一行,最后是一个错误,不能说无法打开grep:-C4 如果我使用-A4和-B4的话,结果是相似的。我假设您需要一个没有GNU扩展的便携式POSIX解决方案(-C NUM、-a NUM和-B NUM都是GNU,模式和/或文件名后面的参数也是GNU) 我不能

我能够在正常的命令行中使用
grep

grep "ABC" Filename -C4
这是给我所需的输出,这是4线以上和以下的匹配模式线

但是,如果在unixshell脚本中使用相同的命令,我将无法grep模式上下的行。它给我的输出是模式匹配的唯一行,最后是一个错误,不能说无法打开
grep
-C4


如果我使用
-A4
-B4

的话,结果是相似的。我假设您需要一个没有GNU扩展的便携式POSIX解决方案(
-C NUM
-a NUM
-B NUM
都是GNU,模式和/或文件名后面的参数也是GNU)

我不能这么做,但我可以。这可以被调用,例如
grepC-C4“ABC”文件名
(假设它被命名为“grepC”,是可执行的,并且在您的
$PATH
中):

#/垃圾箱/垃圾箱
die(){echo“$*\n用法:$0[-C NUMBER]模式[文件]…”>&2;退出2;}
上下文=0#默认值
每箱1元
-C)上下文=“2美元”;第二班;#从“-C 4”中提取“4”
-C*)CONTEXT=“${1#-C}”;移位;#从“-C4”中提取“4”
--|-)移位;#无参数或使用标准输入(隐式)
-*)[-f“$1”]| |死“非法选项”$1';#非选项非文件
以撒
[“$CONTEXT”-ge 0]2>/dev/null | | die“无效上下文”$CONTEXT”
[“$#”=0]&&die“缺少模式”
PATTERN=“$1”
转移
awk'
/“$PATTERN””/{
匹配=“$CONTEXT”
对于(i=1;ii)最后一次打印[i];
打印
下一个
}
匹配{打印;匹配--}
{for(i='$CONTEXT';i>1;i--)last[i]=last[i-1];last[1]=0}
' "$@"
这将
die
设置为致命错误函数,然后从参数中查找所需的上下文行(无论是
-C NUMBER
还是
-CNUMBER
),不支持的选项会出现错误(除非是文件)

如果上下文不是一个数字或没有模式,我们将再次致命地出错

否则,我们将保存该模式,将其移开,并保留将其作为文件传递给awk的其余选项(
“$@”

此awk调用中有三节:

  • 匹配模式本身。这需要结束字符串的单引号部分,以便合并
    $PATTERN
    变量(如果通过
    awk-v
    导入,则可能无法正确操作)。在该匹配之后,我们将上下文的行数存储到
    match
    变量中,循环通过
    last
    散列中保存的前几行(如果我们已经进行了足够多的操作),然后打印它们。然后我们跳到下一行,不评估其他两节
  • 如果有匹配项,我们需要接下来的几行作为上下文。当这一节打印它们时,计数器将递减。新的匹配项(上一节)将重置该计数
  • 我们需要保存前几行,以便在比赛时回忆。这将遍历我们关心的上下文行数,并将它们存储在
    last
    散列中。当前行(
    $0
    )存储在
    last[1]

  • 我假设您需要一个不带GNU扩展的可移植POSIX解决方案(
    -C NUM
    -a NUM
    -B NUM
    都是GNU,模式和/或文件名后面的参数也是GNU)

    我不能这么做,但我可以。这可以被调用,例如
    grepC-C4“ABC”文件名
    (假设它被命名为“grepC”,是可执行的,并且在您的
    $PATH
    中):

    #/垃圾箱/垃圾箱
    die(){echo“$*\n用法:$0[-C NUMBER]模式[文件]…”>&2;退出2;}
    上下文=0#默认值
    每箱1元
    -C)上下文=“2美元”;第二班;#从“-C 4”中提取“4”
    -C*)CONTEXT=“${1#-C}”;移位;#从“-C4”中提取“4”
    --|-)移位;#无参数或使用标准输入(隐式)
    -*)[-f“$1”]| |死“非法选项”$1';#非选项非文件
    以撒
    [“$CONTEXT”-ge 0]2>/dev/null | | die“无效上下文”$CONTEXT”
    [“$#”=0]&&die“缺少模式”
    PATTERN=“$1”
    转移
    awk'
    /“$PATTERN””/{
    匹配=“$CONTEXT”
    对于(i=1;ii)最后一次打印[i];
    打印
    下一个
    }
    匹配{打印;匹配--}
    {for(i='$CONTEXT';i>1;i--)last[i]=last[i-1];last[1]=0}
    ' "$@"
    
    这将
    die
    设置为致命错误函数,然后从参数中查找所需的上下文行(无论是
    -C NUMBER
    还是
    -CNUMBER
    ),不支持的选项会出现错误(除非是文件)

    如果上下文不是一个数字或没有模式,我们将再次致命地出错

    否则,我们将保存该模式,将其移开,并保留将其作为文件传递给awk的其余选项(
    “$@”

    此awk调用中有三节:

  • 匹配模式本身。这需要结束字符串的单引号部分,以便合并
    $PATTERN
    变量(如果通过
    awk-v
    导入,则可能无法正确操作)。在该匹配之后,我们将上下文的行数存储到
    match
    变量中,循环通过
    last
    散列中保存的前几行(如果我们已经进行了足够多的操作),然后打印它们。然后我们跳到下一行,不评估其他两节
  • 如果有匹配项,我们需要接下来的几行作为上下文。当这一节打印它们时,计数器将递减。新的匹配项(上一节)将重置该计数
  • 我们需要保存前几行,以便在比赛时回忆。这将遍历我们关心的上下文行数,并将它们存储在
    last
    散列中。当前行(
    $0
    )存储在
    last[1]

  • 使用
    uname-srv
    的输出更新您的Q。我打赌您使用的是旧版本的SunOS(或许多其他版本),其中的
    -[ABC]
    选项