我正试图想办法从文件中删除一对行,该对中的第一行包含唯一的id,第二行包含一个字符串。
我正在思考一些事情for i in $(cat idlist.txt ); do grep -v -A1 $i file1
但是我不确定如何在每次迭代时将循环输出反馈到它中?有什么提示吗?
我正在改变的文件基本上是
的格式uniqueID.1
OJNEFONEOIWENWEJNEWEJ
uniqueID.2
HHTHANJAHTNTHAJNTEOEJ
我想要一些ID +字符串。
由于
答案 0 :(得分: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
想法是通过向关联数组ids
添加要忽略的标记来处理idlist文件,然后以成对的行处理第二个文件,注意第一行的id,然后打印它和如果ID不在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
答案 1 :(得分:0)
为列表中的每个模式读取和写入文件似乎效率很低。最好一次读取和处理文件,一次性删除所有ID。
如何执行此操作取决于您在该文件idlist.txt
中获得的ID类型。从您将模式传递给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
版本接受“扩展正则表达式”(程序的GNU版本的-r
选项,或BSD版本的-E
选项) ,然后你可以将所有的ID编译成一个正则表达式:
PROGRAM=$(printf '/('; tr '\n' '|' < idlist.txt; printf '.^)/{N;d;}')
sed -r -i '' -e "$PROGRAM" -- file1
(这里.^
是一个不可能匹配的正则表达式;它遵循正则表达式中的最后|
,以确保交替中的最后一个子句没有匹配。)