我有一个名为main_file的文件,其列数可变。 main_file的前两列始终具有相同的字符数和相同的字段分隔符,并且稍后提供各种信息。该行其余部分中的信息可以是任何信息,包括与第一列相同的信息,因此我不能仅grep该字符串。这些行也不一定是唯一的。
aaaa A --------- fdsfadf
aaaa B --------- fasdfa
bbbb A --------- hgfhf
bbbb B --------- hftret jhtruyr
1ulm A --------- tret aaaa A
1ulm X --------- fsdfs fdsfs
1ulm B --------- yttertre ertre
cccc A --------- sdfsa mjhhfdgdf
cccc B --------- werwfds fsa wrew
cccc P --------- fsda wrewr
ghh1 A --------- rwerw wrew
ghh1 G --------- werwe bbbb B
ghh2 A --------- Pewrew trerew rwew
ghh2 G --------- fdss rewrw8
ghh4 A --------- qweqe 321313
ghh4 G --------- 3242 wrewrw
aaaa B --------- fasdfa erwrew
我有一个名为code_list的文件,其中包含所有需要从文件中删除的条目。
aaaa A
aaaa B
bbbb A
bbbb B
cccc A
cccc B
cccc P
我想从main_file中删除或注释掉code_list中有条目的所有行
所以我想得到(以相同的顺序):
* aaaa A --------- fdsfadf
* aaaa B --------- fasdfa
* bbbb A --------- hgfhf
* bbbb B --------- hftret jhtruyr
1ulm A --------- tret aaaa A
1ulm X --------- fsdfs fdsfs
1ulm B --------- yttertre ertre
* cccc A --------- sdfsa mjhhfdgdf
* cccc B --------- werwfds fsa wrew
* cccc P --------- fsda wrewr
ghh1 A --------- rwerw wrew
ghh1 G --------- werwe bbbb B
ghh2 A --------- Pewrew trerew rwew
ghh2 G --------- fdss rewrw8
ghh4 A --------- qweqe 321313
ghh4 G --------- 3242 wrewrw
* aaaa B --------- fasdfa erwrew
或获取:
1ulm A --------- tret utrtry
1ulm X --------- fsdfs fdsfs
1ulm B --------- yttertre ertre
ghh1 A --------- rwerw wrew
ghh1 G --------- werwe lkjl
ghh2 A --------- Pewrew trerew rwew
ghh2 G --------- fdss rewrw8
ghh4 A --------- qweqe 321313
ghh4 G --------- 3242 wrewrw
我尝试运行myscript.sh代码列表
其中myscript.sh是:
#!/bin/bash
while IFS='' read -r line || [[ -n "$line" ]]; do
awk '{if(substr($0,2,7) == "'$line'") {print "*"$0}else{print $0}}' main_file > out
done < "$1"
但出现错误“未终止的字符串” 当我尝试
awk '{if(substr($0,2,7) == "aaaa A") {print "*"$0}else{print $0}}' main_file > out
然后它起作用。但是文件code_list太长了,无法手动编写每个名称,而且我无法以任何方式将其设置为变量。
删除或注释掉这些行的最佳方法是什么?
答案 0 :(得分:2)
在这里,您可以使用NR == FNR
技术来让awk处理两个文件。当NR == FNR
时,表示正在处理的记录号与当前文件中的记录号相同,换句话说,您正在处理参数列表中的第一个文件(在这种情况下,code_list
)
第一个文件的关联操作是为我们在处理第二个文件(main_file
)时建立查找表。
由于第一个操作中的next
语句使awk立即转到下一条记录而无需执行任何其他操作,因此当我们执行第二步时,我们知道我们正在处理第二个文件。第二步仅具有以下条件:前两个字段不在查找表中。在这种情况下,它会执行默认操作,即打印该行。
$ awk 'NR == FNR {a[$1 FS $2]; next} !(($1 FS $2) in a)' code_list main_file
1ulm A --------- tret aaaa A
1ulm X --------- fsdfs fdsfs
1ulm B --------- yttertre ertre
ghh1 A --------- rwerw wrew
ghh1 G --------- werwe bbbb B
ghh2 A --------- Pewrew trerew rwew
ghh2 G --------- fdss rewrw8
ghh4 A --------- qweqe 321313
ghh4 G --------- 3242 wrewrw
答案 1 :(得分:2)
我的其中一项工作:
awk 'NR==FNR {a[$0]++;next} {b=substr($0,2,7)} !(b in a)' filter data
awk 'NR==FNR {a[$0]++;next} !(($1" "$2) in a)' filter data
1ulm A --------- tret aaaa A
1ulm X --------- fsdfs fdsfs
1ulm B --------- yttertre ertre
ghh1 A --------- rwerw wrew
ghh1 G --------- werwe bbbb B
ghh2 A --------- Pewrew trerew rwew
ghh2 G --------- fdss rewrw8
ghh4 A --------- qweqe 321313
ghh4 G --------- 3242 wrewrw
答案 2 :(得分:2)
$ awk '{k=$1 FS $2} NR==FNR{a[k]; next} !(k in a)' code_list main_file
1ulm A --------- tret aaaa A
1ulm X --------- fsdfs fdsfs
1ulm B --------- yttertre ertre
ghh1 A --------- rwerw wrew
ghh1 G --------- werwe bbbb B
ghh2 A --------- Pewrew trerew rwew
ghh2 G --------- fdss rewrw8
ghh4 A --------- qweqe 321313
ghh4 G --------- 3242 wrewrw
$ awk '{k=$1 FS $2} NR==FNR{a[k]; next} {print (k in a ? "*" : "") $0}' code_list main_file
* aaaa A --------- fdsfadf
* aaaa B --------- fasdfa
* bbbb A --------- hgfhf
* bbbb B --------- hftret jhtruyr
1ulm A --------- tret aaaa A
1ulm X --------- fsdfs fdsfs
1ulm B --------- yttertre ertre
* cccc A --------- sdfsa mjhhfdgdf
* cccc B --------- werwfds fsa wrew
* cccc P --------- fsda wrewr
ghh1 A --------- rwerw wrew
ghh1 G --------- werwe bbbb B
ghh2 A --------- Pewrew trerew rwew
ghh2 G --------- fdss rewrw8
ghh4 A --------- qweqe 321313
ghh4 G --------- 3242 wrewrw
* aaaa B --------- fasdfa erwrew
答案 3 :(得分:1)
我建议将文件code_list
中的数据转换为grep
的模式,并固定到行的开头
sed 's/^/^/' code_list > code_list2
编辑:如果code_list
和main_file
都包含相同的前导空格,则此方法将起作用。
假设文件code_list
仅包含一个前导空格,则结果文件code_list2
将包含
^ aaaa A
^ aaaa B
^ bbbb A
^ bbbb B
^ cccc A
^ cccc B
^ cccc P
如果前导空格可能不同(或不存在),则可以扩展替换:
sed 's/^ */^ */' code_list > code_list2
这将删除任意数量的前导空格,并为任意数量的前导空格添加一个模式。处理标签也需要进行其他更改。
生成的文件code_list2
将包含
^ *aaaa A
^ *aaaa B
^ *bbbb A
^ *bbbb B
^ *cccc A
^ *cccc B
^ *cccc P
(编辑结束)
然后使用它来提取不匹配的行
grep -v -f code_list2 main_file
有了这个我
1ulm A --------- tret aaaa A
1ulm X --------- fsdfs fdsfs
1ulm B --------- yttertre ertre
ghh1 A --------- rwerw wrew
ghh1 G --------- werwe bbbb B
ghh2 A --------- Pewrew trerew rwew
ghh2 G --------- fdss rewrw8
ghh4 A --------- qweqe 321313
ghh4 G --------- 3242 wrewrw
如果您使用支持<( command )
的shell,例如bash
,您可以将两个命令组合为
grep -v -f <(sed 's/^/^/' code_list) main_file
编辑:或处理不同的前导空格
grep -v -f <(sed 's/^ */^ */' code_list) main_file