【问题标题】:get Nth line in file after parsing another file解析另一个文件后获取文件中的第 N 行
【发布时间】:2012-04-13 14:41:38
【问题描述】:

我有一个大文件作为

foo:43:sdfasd:daasf
bar:51:werrwr:asdfa
qux:34:werdfs:asdfa
foo:234:dfasdf:dasf
qux:345:dsfasd:erwe
...............

这里第 1 列 foo、bar 和 qux 等是文件名。和第 2 列 43,51, 34 等是行号。我想为每个文件(在第一列中指定)打印第 N 行(由第二列指定)。 如何在 unix shell 中实现上述自动化。 实际上上面的文件是在编译时生成的,我想在代码中打印警告行。

-谢谢,

【问题讨论】:

    标签: bash shell unix csh


    【解决方案1】:
    while IFS=: read name line rest
    do
        head -n $line $name | tail -1
    done < input.txt
    

    【讨论】:

    • 如果你只想要有问题的行:head -n $line $name | tail -1
    【解决方案2】:

    while IFS=: read file line message; do
        echo "$file:$line - $message:"
        sed -n "${line}p" "$file"
    done <yourfilehere
    

    【讨论】:

    • 为了效率:sed -n "${line}{p;q}"
    • 在更改 IFS 之前保存 IFS 并在不再需要后恢复到原始状态是一个很好的做法。喜欢:OFS=$IFS; ...; IFS=$OFS
    • vyegorov:以上仅在读取命令期间更改它。即使在循环体内部,它也会恢复到默认值。
    【解决方案3】:
    awk 'NR==4 {print}' yourfilename
    
    or
    
    cat yourfilename | awk 'NR==4 {print}'
    

    上述的将适用于您文件中的第 4 行。您可以根据需要更改数字。

    【讨论】:

    • 传递行号:awk -v n=$lineno 'NR==n {print;exit}' file
    • 如果文件在另一个文件中间被处理,那么我们应该使用 -v 选项。但如果它是一个显式过程,那么我们不需要 -v 选项。
    【解决方案4】:

    就在 awk 中,但性能可能比 @kev 或 @MarkReed 的答案差。 但是它只处理每个文件一次。需要 GNU awk

    gawk -F: '
        BEGIN {OFS=FS}
        { 
            files[$1] = 1
            lines[$1] = lines[$1] " " $2
            msgs[$1, $2] = $3 
        }
        END {
            for (file in files) {
                split(lines[file], l, " ")
                n = asort(l)
                count = 0
                for (i=1; i<=n; i++) {
                    while (++count <= l[i])
                        getline line < file
                    print file, l[i], msgs[file, l[i]]
                    print line
                }
                close(file)
            }
        }
    '
    

    【讨论】:

      【解决方案5】:

      这可能对你有用:

      sed 's/^\([^,]*\),\([^,]*\).*/sed -n "\2p" \1/' file |
      sort -k4,4 | 
      sed ':a;$!N;s/^\(.*\)\(".*\)\n.*"\(.*\)\2/\1;\3\2/;ta;P;D' |
      sh
      

      【讨论】:

        【解决方案6】:
         sed -nr '3{s/^([^:]*):([^:]*):.*$/\1 \2/;p}' namesNnumbers.txt 
         qux 34
        
        • -n 默认不输出,
        • -r 正则表达式(使用括号简化)
        • 在第 3 行执行 {...;p}(最后打印)
        • 用 foo bar 代替 foobarbaz

        所以要使用这些值:

        fnUln=$(sed -nr '3{s/^([^:]*):([^:]*):.*$/\1 \2/;p}' namesNnumbers.txt)
        
        fn=$(echo ${fnUln/ */})
        ln=$(echo ${fnUln/* /})
        sed -n "${ln}p" "$fn"
        

        【讨论】:

        • 问题是询问如何从文件“qux”中获取第 34 行(对于所有其他行也是如此)
        • @glennjackman:我知道。使用“qux”和“34”是微不足道的:sed -n "${lineno}p" "$filename"。你认为我应该在我的回答中加入这个吗?
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-10-28
        • 1970-01-01
        • 2011-11-08
        • 1970-01-01
        • 2019-05-21
        • 2020-09-27
        相关资源
        最近更新 更多