代码之家  ›  专栏  ›  技术社区  ›  ahmet alp balkan

如果前一行是前缀,则删除行(从输出中省略)

  •  2
  • ahmet alp balkan  · 技术社区  · 7 年前

    这与问题非常相似。” remove duplicate lines with similar prefix “但情况恰恰相反:

    输入 排序的 字符串(在本例中是目录)如下:

    a/
    a/b/c/
    a/d/
    bar/foo/
    bar/foo2/
    c/d/
    c/d/e/
    

    我想从输出中删除这些行, 如果前一行是当前行的前缀 . 在这种情况下,输出将是:

    a/
    bar/foo/
    bar/foo2/
    c/d/
    

    这在Python等语言中很容易编写代码,但在本例中,我使用的是shell环境(bash、sort、sed、awk…)。(重新排序很好。)

    4 回复  |  直到 7 年前
        1
  •  4
  •   jxc    7 年前

    使用awk:

    awk '{if(k && match($0, k))next; k="^"$0}1' file
    

    k=“^”$0将模式锚定到字符串的开头。

    可能需要 NF>0 在主块前以防有空行。

    更新: 如果变量中存在regex元字符,则可能存在问题 k ,下面这行不使用regex应该更好:

    awk '{if(k && index($0, k)==1)next; k=$0}1' file
    

    更新-2: 谢谢@ed,我已经调整了第二种方法,将非空行计算为零(空行将保持原样):

    awk '{if(k!="" && index($0,k)==1)next;k=$0}1' file
    
        2
  •  2
  •   David C. Rankin    7 年前

    bash本身(实际上是posix shell)提供了您所需要的一切 带删除子字符串的参数扩展 . 您需要做的只是检查您所读的行是否与删除的前缀匹配。如果没有,您就有一个前缀行,否则,您就有一个非前缀行。然后,只需输出未加前缀的行,并将前缀设置为当前行——然后重复,例如。

    #!/bin/bash
    
    pfx=    ## prefix
    
    ## read each line
    while read -r line; do 
        ## if no prefix or line matches line with prefix removed
        if [ -z "$pfx" -o "$line" = "${line#$pfx}" ]
        then
            printf "%s\n" "$line"   ## output lile
            pfx="$line"             ## set prefix to line
        fi
    done < "$1"
    

    ( 注: 如果输入文件不包含POSIX文件结尾,例如 '\n' 在文件的最后一行,您应该检查行的内容作为 while ,例如 while read -r line || [ -n "$line" ]; do ... )

    示例输入文件

    $ cat string.txt
    a/
    a/b/c/
    a/d/
    bar/foo/
    bar/foo2/
    c/d/
    c/d/e/
    

    示例使用/输出

    $ bash nonprefix.sh string.txt
    a/
    bar/foo/
    bar/foo2/
    c/d/
    
        3
  •  1
  •   xxfelixxx    7 年前

    -n 然后执行 -e 下面的程序,检查当前行的开头是否与最后一行匹配,打印不匹配的行。

    perl -ne 'print unless m|^$last|; chomp($last=$_);' file_list.txt
    
        4
  •  1
  •   Ed Morton    7 年前
    $ awk 'NR==1 || index($0,prev)!=1{prev=$0; print}' file
    a/
    bar/foo/
    bar/foo2/
    c/d/