【问题标题】:find line number of a word in a file在文件中查找单词的行号
【发布时间】:2014-08-18 00:51:54
【问题描述】:

我有一个文件:file.txt,其中包含以下数据。 GNU grep 版本:2.5.1,系统管理员拒绝将其升级到更高版本,因为它可能会影响生产

This is a file, my name is Karl, what is this process, karl is karl junior, file is a test file, file's name is file.txt
My name is not Karl, my name is Karl Joey
What is your name?
Do you know your name and what it is?

当我运行以下命令以使用以下命令在此文件中获取单词“is”的行号时,它会给我如下输出:

$ grep -now "is" file.txt

1:is
is
is
is
is
is
2:is
is
3:is
4:is

我可以运行什么命令来获得以下输出:

1:is
1:is
1:is
1:is
1:is
1:is
2:is
2:is
3:is
4:is

is:1,1,1,1,1
is:2,2
is:3
is:4

如果我正在尝试以下命令,我已经接近了,但我想用 is 和 is 替换 1(逗号分隔)
grep -now "is" file.txt | tr '\012' ' '| sed "s/([0-9]:)/\n\1/g" | grep "."

1:is is is is is is
2:is is
3:is
4:is

【问题讨论】:

    标签: awk grep find line word


    【解决方案1】:

    如果您可以使用perl,那么这里使用他们的last match start (@-)last match end (@+)

    perl -lne '
    while ($_ =~ /\bis\b/g) {
        print "$.:", substr($_, $-[0], $+[0] - $-[0]);
    }' file
    1:is
    1:is
    1:is
    1:is
    1:is
    1:is
    2:is
    2:is
    3:is
    4:is
    

    基于 OP 要求的新格式:

    perl -lne '
        $found =()= /\bis\b/g;
        print substr($_, $-[0], $+[0] - $-[0]), ":", join (",", ($.) x $found);
    ' file
    is:1,1,1,1,1,1
    is:2,2
    is:3
    is:4
    

    使用 GNU awk 作为单词边界:

    gawk '{
        n = gsub(/\<is\>/,"");
        printf "%s:", "is"; 
        for (i=1; i<=n; i++) printf "%s%s", NR, (i==n?RS:",")
    }' file
    is:1,1,1,1,1,1
    is:2,2
    is:3
    is:4
    

    使用香草awk(礼貌Ed Morton(见cmets)):

    awk '
    {
        n = gsub(/(^|[^[:alpha:]])is([^[:alpha:]]|$)/,"");
        printf "%s:", "is";
        for (i=1; i<=n; i++) printf "%s%s", NR, (i==n?RS:",")
    }' file
    is:1,1,1,1,1,1
    is:2,2
    is:3
    is:4
    

    【讨论】:

    • awk 解决方案是 gawk 特有的,由单词分隔符 \&lt;\&gt; 提供。因为 OP 无法安装更新的grep,我猜他没有gawk。虽然他显然有 perl 所以谁知道......
    • @EdMorton 是的,已更新答案以反映这一点。你是对的,在此之后发布了另一个问题,其中包括一个奇怪的格式请求。 :)
    • 是的,我看到了。立即产生他现在似乎想要的输出而不是产生他最初想要但现在似乎不想要的输出然后将其转换为他现在想要的输出会更容易。没有意义。哦,好吧...
    • 仅供参考,您可以将 \&lt; 替换为 (^|[^[:alpha:]]) 并将 \&gt; 替换为 ([^[:alpha:]]|$),以添加非 gawk 版本。
    • @EdMorton 好主意,考虑到它是公认的解决方案,它可能会帮助其他人寻找香草awk 解决方案。谢谢,已经添加了那个版本。 :)
    【解决方案2】:
    grep -o -n "is" file.txt
    

    似乎可以在我的系统上运行。

    【讨论】:

    • 这行不通。在第一行加入一个新句子,可以写:我不喜欢论文。然后它将最终打印: 5:is is .. you
    • 这就是我使用“-now”选项的原因(参见-w)。 grep 版本为:2.5.1
    【解决方案3】:

    如果您可以升级grep 的版本,它应该可以修复它:

    # grep --version
    grep (GNU grep) 2.16
    Copyright (C) 2014 Free Software Foundation, Inc.
    License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
    This is free software: you are free to change and redistribute it.
    There is NO WARRANTY, to the extent permitted by law.
    
    Written by Mike Haertel and others, see <http://git.sv.gnu.org/cgit/grep.git/tree/AUTHORS>.
    # grep -now is file
    1:is
    1:is
    1:is
    1:is
    1:is
    1:is
    2:is
    2:is
    3:is
    4:is
    

    使用perl模仿grep的输出:

    # perl -lne '$x = "is"; $c = () = /\b$x\b/g; while ($c--) { print "$.:$x"; }' file
    1:is
    1:is
    1:is
    1:is
    1:is
    1:is
    2:is
    2:is
    3:is
    4:is
    

    另一个:

    # perl -lne '$x = "is"; $c = () = /\b$x\b/g; next unless $c--; $t = "${x}:$."; $t .= ",$." while ($c--); print $t' file
    is:1,1,1,1,1,1
    is:2,1
    is:3
    is:4
    

    【讨论】:

    • 我认为我们的 SYS 管理员不会升级 grep。有没有其他办法。谢谢。
    • 谢谢,我认为升级就可以了。实际上我不想创建任何变量,否则它会是 shell 中的 2 个衬垫。非常感谢
    • 能否仅使用 sed 和 awk 或任何 Linux 命令(在新格式输出上)而不是使用 Perl 来完成?
    • @user1513848 awk 更加神秘。也许你需要 GNU awk 来让它不那么神秘。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-25
    • 1970-01-01
    • 1970-01-01
    • 2013-08-05
    相关资源
    最近更新 更多