使用二进制模式字符串从文件中删除行

时间:2018-05-30 18:06:58

标签: bash shell awk grep

我有两个文件。文件A包含用N行写的文本,文件B包含一个二进制模式字符串0和1,它也有N长度。

我想从文件A中删除与文件B中包含0的行号相同的行。

我读过用awk做这个可能是个好主意,但我不知道如何使用它。

文件非常长,例如2000行(它们是视频轨迹)

例如:

档案A:

Line 1: 123456
Line 2: 789012
Line 3: 345678
Line 4: 901234

档案B:

Line 1: 1
Line 2: 0
Line 3: 0
Line 4: 1

执行后:

档案A:

Line 1: 123456
Line 2: 901234

8 个答案:

答案 0 :(得分:6)

您可以使用pastecut

paste fileB fileA | grep '^1' | cut -f2-
  • paste fileB fileA - 并排粘贴文件内容,由选项卡
  • 分隔
  • grep '^1' - 过滤以1
  • 开头的行
  • cut -f2- - 提取我们需要的内容

cutpaste都使用制表符作为默认分隔符。

这与Benjamin's解决方案非常相似。这里的一个小优点是,即使fileA每行还有多个字段,它也能正常工作。

答案 1 :(得分:3)

您可以使用decorate – filter – undecorate模式:

paste fileA fileB | grep -v '0$' | cut -f1

这会打印每个文件的行(paste),然后过滤以0grep)结尾的行,然后从第二个文件中删除行(cut)。

如果fileA包含用于pastecut的分隔符(默认情况下为标签符号),则会中断。为了避免这种情况,我们可以交换文件(参见codeforester's answer)或使用类似

的文件
paste fileA fileB | sed -n '/1$/s/\t.$//p'

(如果行以1结尾,请删除标签和最后一个字符,然后打印)或

paste fileA fileB | grep -Po '.*(?=\t1$)'

(仅匹配以1结尾的行,使用零宽度前瞻以排除制表符和1匹配);最后一个解决方案需要一个支持Perl兼容正则表达式(PCRE)的grep,例如GNU grep。

答案 2 :(得分:3)

这里有很多有趣的答案。这是一个重击:

while IFS= read -r -u3 line; IFS= read -r -u4 bool; do 
    ((bool == 1)) && printf "%s\n" "$line"
done 3<fileA 4<fileB

这比其他解决方案要慢得多。

答案 3 :(得分:3)

假设输入文件中并不存在Line 1:等,您只需要:

awk 'NR==FNR{a[NR]=$0;next} a[FNR]' fileB fileA

答案 4 :(得分:2)

单个awk命令可以从两个文件中读取。

awk '(getline flag < "fileB") > 0 && flag' fileA

fileA读取每一行后,从fileB读取一行到变量标志,并测试其整数值是否为真。对于真值,将打印fileA的行。

根据您的awk版本,您可能需要使用int(flag)flag+0强制将值视为整数而不是普通的非空字符串。< / p>

答案 5 :(得分:2)

另一个paste / awk解决方案。如果数据中出现选项卡,则找到另一个分隔符。

paste file2 file1 | awk -F'\t' '$1{print $2}' 

答案 6 :(得分:1)

编辑: @ codeforester的评论如果Line 1Line 2不属于您的File1和File2,那么以下内容可能有所帮助。

awk 'FNR==NR{a[FNR]=$0;next} $0!=0{print a[FNR]}' filea fileb

解决方案第二: 首先读取fileb文件然后再读取filea。

awk 'FNR==NR{if($0!=0){a[FNR]=$0};next} a[FNR]' fileb filea

如果OP在他/她的文件中包含字符串line1,line2,则解决方案1的替代方案。

关注awk也可能有所帮助。

awk '
FNR==NR{
  a[FNR]=$NF;
  next}
$NF!=0{
  printf("%s%s\n","Line " ++count": ",a[FNR])
}' filea fileb

答案 7 :(得分:0)

pastesed组合:

paste -d'\n' fileB fileA | sed -n '/^1$/{n;p}'
123456
901234

您交错文件:

1
123456
0
789012
0
345678
1
901234

然后使用sed打印直接跟随仅1的行的行。但是,如果您的条目仅由1中的fileA组成,则此操作将无法正常运行。如果是这种情况,则必须使用以下sed命令,如果我们当前正在处理奇数/偶数行,则需要考虑该命令:

paste -d'\n' fileB fileA | sed -n '1~2{/^1$/{n;p}}'