1

我试图想办法从文件中删除一对行,该对中的第一行包含一个唯一的 id,第二行是一个字符串。我在想一些事情

for i in $(cat idlist.txt ); do grep -v -A1 $i file1 

但是我不确定如何在每次迭代时将循环的输出通过管道传输回它?有小费吗?

我正在更改的文件基本上是以下格式

uniqueID.1
OJNEFONEOIWENWEJNEWEJ
uniqueID.2
HHTHANJAHTNTHAJNTEOEJ

我想删除一些 ids + 字符串。

谢谢

4

2 回答 2

0

awk在这种情况下,可能是一个不错的工具选择。bash这是包含在脚本中的基本思想的快速版本:

#!/bin/bash

awk '
FNR == 1 { filenum++ }
filenum == 1 { ids[$0] = 1 }
filenum == 2 {
    if ((FNR % 2) == 1) { id = $0 }
    else if (ids[id] != 1) { print id; print }
}
' idlist.txt file.txt

这个想法是通过将要忽略的标签添加到关联数组来处理 idlist 文件ids,然后成对处理第二个文件,注意第一行的 id,然后打印它,如果 id 不是,则打印下一行t 中ids

mv如果您需要“就地”修改文件,与已经建议的相同的东西可以在这里工作。

成绩单:

$ cat idlist.txt 
id.2
id.4
id.6
$ cat file.txt 
id.1
stuff 1
id.2
stuff 2
id.3
stuff 3
id.4
stuff 4
id.5
stuff 5
id.6
stuff 6
id.7
stuff 7
$ ./skipper.sh 
id.1
stuff 1
id.3
stuff 3
id.5
stuff 5
id.7
stuff 7
于 2013-10-28T17:40:50.567 回答
0

为列表中的每个模式读取和写入文件似乎非常低效。最好只读取和处理一次文件,一次删除所有 id。

如何执行此操作取决于您在该文件中获得的 ID 类型idlist.txt。从您将模式传递给 的方式grep来看,它们似乎必须是单词或简单的正则表达式,因此您可以尝试以下方法。

首先,将 ID 转换为sed程序:

PROGRAM=$(while read ID; do echo "/$ID/{N;d;}"; done < idlist.txt)

然后用于sed运行程序并就地更新文件:

sed -i '' -e "$PROGRAM" -- file1

程序的工作方式是/$ID/匹配包含 id 的行,然后N命令从文件中读取下一行,然后d命令删除这两行。其他行打印正常。(显然,这取决于是否$ID是一个不包含/字符的有效基本正则表达式。)

如果您有一个sed接受“扩展正则表达式”-r的版本(程序的 GNU 版本的-E选项,或 BSD 版本的选项),那么您可以将所有 ID 编译成一个正则表达式:

PROGRAM=$(printf '/('; tr '\n' '|' < idlist.txt; printf '.^)/{N;d;}')
sed -r -i '' -e "$PROGRAM" -- file1

(这.^是一个不可能匹配的正则表达式;它跟|在正则表达式中的 final 之后,以确保交替中的 final 子句没有匹配。)

于 2013-10-28T20:46:31.773 回答