一线排除异常的模式

时间:2018-12-18 04:12:57

标签: bash awk sed text-processing

我的目标是制作优雅的单面纸

输入

源文件,包含字符串列表:

foo123
bar12356
foo999
var8292
bar922
link991
bar8
var000

具有黑名单模式的文件:

bar
link

白名单文件(可以包含多个条目):

bar922

任务: 我们需要根据黑名单中的模式删除字符串,同时保留白名单中的精确匹配项。需要注意的是,我们都需要以与原始文件中相同的顺序保存输出,并且如果白名单字符串在初始文件中不存在,我们不应该添加白名单字符串< / em>。

输出

foo123
foo999
var8292
bar922
var000

5 个答案:

答案 0 :(得分:2)

您可以为此使用<FieldArray name="policies" component={this.renderPolicies} /> 这个小命令。这个想法是您在黑名单文件(renderPolicies = ({ fields, meta }) => { return ( <ul> <li> <button type="button" onClick={() => fields.push({})}> Add Policy </button> {this.renderError(meta)} </li> {fields.map((policy, index) => ( <li key={index}> <button type="button" title="Remove Policy" onClick={() => fields.remove(index)} /> <h4>Policy #{index + 1}</h4> <Field name={`${policy}.id`} type="text" component={renderInput} label="Id" /> </li> ))} </ul> ); )上使用awk命令,使其内容用paste分隔,例如bl以及白名单文件(|)。

生成文件后,我们对文件的内容进行正则表达式匹配,条件是这些条目可能在白名单中,或者这些条目不应该在黑名单中。

bar|link

注释中有一点要处理wl文件中的空行。如果您怀疑它们,请使用awk -v bl=$(paste -sd'|' bl) -v wl=$(paste -sd'|' wl) '$0 ~ wl || $0 !~ bl' file 对其进行修复。

答案 1 :(得分:2)

David C. Rankin的解决方案非常优雅,不会造成太多混乱。如果要保留顺序,可以将其扩展为:

$ { grep -wf wl file; grep -vf bl file ;} | grep -wf - file

请注意,我们为白名单引入了-w标志,以确保单词匹配。

备注:这是一个合格的解决方案,它是迄今为止最有效的解决方案!

答案 2 :(得分:1)

您可以使用grep -f创建一个简单的 one-liner 来从您的白名单和黑名单文件中读取模式,并包括-v以将黑名单的内容反转列表,然后使用stdin上的组合结果来创建有序文件,例如

输入,白名单,黑名单文件

$ cat file
foo123
bar12356
foo999
var8292
bar922
link991
bar8
var000

白名单

$ cat white
bar922

黑名单

$ cat black
bar
link

修改 与@kvantour进行沟通工作后,您可以使用流程替换来在stdin上为列表进行最终排序,例如

$ grep -wof - file < <(grep -v -f black file; grep -f white file)
foo123
foo999
var8292
bar922
var000

答案 3 :(得分:0)

也可以使用Perl解决此问题。

> cat stan.in
foo123
bar12356
foo999
var8292
bar922
link991
bar8
var000
> cat white
bar922
> cat black
bar
link
> perl -lne 'BEGIN{ @w=qx(cat white);@b=qx(cat black);}chomp for(@w);chomp for(@b); $x=$_;print if grep {$x=~/$_/} @w; print if scalar(grep { $x=~/$_/g} @b)==0' stan.in 
foo123
foo999
var8292
bar922
var000
> 

$ perl -lne 'BEGIN{ @w=qx(cat white);@b=qx(cat black);}chomp for(@w,@b);$x=$_;print if grep {$x=~/$_/} @w; print if scalar(grep { $x=~/$_/g} @b)==0' stan.in
foo123
foo999
var8292
bar922
var000

答案 4 :(得分:0)

只是为了好玩,这是一个使用bash数组的选项 1

# Gather our lists...
mapfile -t a < input.txt; mapfile -t wl < wl; mapfile -t bl < bl

# And store the whitelist as indices for easier handling...
declare -A wl_a=(); for x in "${wl[@]}"; do wl_a["$x"]=1; done

# Then step through the data array,
for x in "${!a[@]}"; do
  # detecting and skipping whitelist matches,
  [[ "${wl_a[${a[$x]}]}" = 1 ]] &&
    printf 'wl: %s\n' "$x" &&
    continue
  # and deleting blacklist matches.
  for y in "${bl[@]}"; do
    [[ "${a[$x]}" = "$y"* ]] &&
      printf 'bl: %s\n' "${a[$x]}" &&
      unset a["$x"]
  done
done

结果是数组${a[@]}以原始顺序包含您的数据,并删除了适当的黑名单项目。您可以使用declare -p aprintf '%s\n' "${a[@]}"查看结果。

请注意,这是实现这一目标的一种 crazy 方法(而且显然不是单一方法),您可以在awk中更有效地完成很多工作。但这至少是一个纯bash解决方案,并且不使用任何外部工具。

1。这取决于bash 4+,因为其中一个数组是关联的。