【问题标题】:search for multiple conditioned string with awk使用 awk 搜索多个条件字符串
【发布时间】:2013-01-04 10:26:48
【问题描述】:

我有一组看起来像这样的数据

col1    col2    col3    col4
ABC1    DEF1    GHI1    cond1
ABC2    DEF2    GHI2    cond1-cond2
ABC3    DEF3    GHI3    cond2/cond1
ABC4    DEF4    GHI4    cond2 cond1
ABC5    DEF5    GHI5    cond4/cond1
ABC6    DEF6    GHI6    cond1
ABC7    DEF7    GHI7    mcond1
ABC8    DEF8    GHI8    cond2
ABC9    DEF9    GHI9    cond1 at 50
ABCa    DEFa    GHIa    con cond1
ABCb    DEFb    GHIb    no. cond1
ABCc    DEFc    GHIc    cond1 something
ABCc    DEFc    GHIc    Mcond1

我正在尝试编写几个命令来根据“col4”来分隔数据以获取:

  1. 一个包含字符串“cond1”的文件,在它之前或之后有任何内容,除了“M”和“m”字母。我目前正在为此使用这个命令(显然不排除 M 和 m):

    awk 'BEGIN{IGNORECASE=1} $4 ~ /.cond1/ || $4 ~ /cond1./ ' /filepath.tab
    

    请不要在第 4、9 和 11 行数据中包含“cond1”和其他字符串之间的空格,我希望将其包含在文件中。 (命令中的“.”是否包含空格?)

  2. 我写了一个命令来获取一个仅在“col4”中包含“cond1”的文件

    awk 'BEGIN{IGNORECASE=1} $4 ~ /^cond1$/ '  /filepath.tab
    

    大多数数据都可以正常工作,尽管我在结果中发现了这 2 个错误:

    ABC9    DEF9    GHI9    cond1 at 50
    ABCc    DEFc    GHIc    cond1 something
    

谁能帮我解决这两个命令? 谢谢。

我正在寻找不包含任何重复的 3 个文件的输出,这是一个示例: File1(包含所有与 cond1 的组合):

col1    col2    col3    col4
ABC2    DEF2    GHI2    cond1-cond2
ABC3    DEF3    GHI3    cond2/cond1
ABC4    DEF4    GHI4    cond2 cond1
ABC5    DEF5    GHI5    cond4/cond1
ABC9    DEF9    GHI9    cond1 at 50
ABCa    DEFa    GHIa    con cond1
ABCb    DEFb    GHIb    no. cond1
ABCc    DEFc    GHIc    cond1 something

File2(仅包含 cond1):

col1    col2    col3    col4
ABC1    DEF1    GHI1    cond1
ABC6    DEF6    GHI6    cond1

File3(包含 file1 和 file2 中未包含的任何内容):

col1    col2    col3    col4
ABC7    DEF7    GHI7    mcond1
ABC8    DEF8    GHI8    cond2
ABCc    DEFc    GHIc    Mcond1

注意3个文件的总行数与原文件相同 如果这听起来很复杂,我很抱歉,但我确实有这种情况。

【问题讨论】:

  • 你想要的输出是什么!
  • 列之间的分隔符是什么?是标签吗?如果其空间第 11 行第 4 列将不包含cond1。这是第 5 列
  • 是的,它是一个制表符分隔的文件,有时单词之间有一个空格。 (我确信这不是不同的列,因为这是一个大文件,我用 cut 只取出这 4 列)
  • 看我的回答。它应该可以工作。

标签: linux unix sed awk


【解决方案1】:

问题是第 4 列中有空格,并且您的文件未按预期格式化尝试 awk -F'\t' {print $4} file 并注意它可能不是您所期望的。

先用sed将文件转成CSV格式

$ sed 's/\s\+/,/;s/\s\+/,/;s/\s\+/,/;' file
col1,col2,col3,col4
ABC1,DEF1,GHI1,cond1
ABC2,DEF2,GHI2,cond1-cond2
ABC3,DEF3,GHI3,cond2/cond1
ABC4,DEF4,GHI4,cond2 cond1
ABC5,DEF5,GHI5,cond4/cond1
ABC6,DEF6,GHI6,cond1
ABC7,DEF7,GHI7,mcond1
ABC8,DEF8,GHI8,cond2
ABC9,DEF9,GHI9,cond1 at 50
ABCa,DEFa,GHIa,con cond1
ABCb,DEFb,GHIb,no. cond1
ABCc,DEFc,GHIc,cond1 something
ABCc,DEFc,GHIc,Mcond1

这只会将前 3 个空白组转换为逗号,然后根据需要留下 col4。要将更改存储在文件中,请使用 -i 选项:

sed -i 's/\s\+/,/;s/\s\+/,/;s/\s\+/,/;' file

现在可以使用字段分隔符,

awk 'BEGIN{FS=",";OFS="\t"} NR==1{print $1,$2,$3,$4} $4~/cond1./|| $4~/[^mM]cond1/{print $1,$2,$3,$4}' file
col1    col2    col3    col4
ABC2    DEF2    GHI2    cond1-cond2
ABC3    DEF3    GHI3    cond2/cond1
ABC4    DEF4    GHI4    cond2 cond1
ABC5    DEF5    GHI5    cond4/cond1
ABC9    DEF9    GHI9    cond1 at 50
ABCa    DEFa    GHIa    con cond1
ABCb    DEFb    GHIb    no. cond1
ABCc    DEFc    GHIc    cond1 something

$ awk 'BEGIN{FS=",";OFS="\t"} NR==1{print $1,$2,$3,$4} $4~/^cond1$/{print $1,$2,$3,$4}' file 
col1    col2    col3    col4
ABC1    DEF1    GHI1    cond1
ABC6    DEF6    GHI6    cond1

$ awk 'BEGIN{FS=",";OFS="\t"} $4!~/cond1/ || $4~/[Mm]cond1/{print $1,$2,$3,$4}' file
col1    col2    col3    col4
ABC7    DEF7    GHI7    mcond1
ABC8    DEF8    GHI8    cond2
ABCc    DEFc    GHIc    Mcond1

只需重定向以保存新文件awk '{...}' > file1

【讨论】:

  • 您好,感谢您的指挥。对于第一个命令(将其转换为逗号分隔文件之后),甚至单词之间的空格也变成了逗号。所以我丢失了“cond1 at 50”、“cond1 something”、“cond2 cond1”、“con cond1”和“no. cond1”字段。
  • @Error404 no sed 命令的构造方式仅用逗号替换前 3 个空白组,我已经更新了我的答案来解释这一点。
  • 是的,伙计,谢谢你的回答......现在我明白了命令,我知道如何钓鱼,我会每天吃:)
【解决方案2】:

由于您的字段是制表符分隔的,请在 BEGIN 块中使用 FS="\t"。你的条件也不合适。所以我改了。

awk 'BEGIN{IGNORECASE=1; FS="\t"; } $4 ~ /cond1/ && $4 !~ /mcond1|cond1m/' data

【讨论】:

  • 感谢您的命令。实际上这是一种很好的方式,但我想在这个命令中添加一些东西。如果我在 col4“mcond1 cond1”中有这个,那么如果 mcond1 和 cond1 同时存在,我希望它被包括在内,如果 mcond1 是单独的或与其他任何东西一起,那么不。这个怎么说呢?
  • 这个过度匹配,包括第 1 行和第 6 行,加上没有标题。
【解决方案3】:

您只需通过一次即可完成任务。运行如下:

awk -f script.awk file

script.awk的内容:

BEGIN {
    FS="\t"
}

NR==1 {
    r=$0
    next
}

{
    i = ($4 == "cond1" ? 2 : ($4 ~ /cond1/ && $4 !~ /[Mm]cond1/ ? 1 : 3))
    print (!a[i]++ ? r ORS : "") $0 > "file" i ".txt"
}

grep . file[1-3].txt的结果:

file1.txt:col1  col2    col3    col4
file1.txt:ABC2  DEF2    GHI2    cond1-cond2
file1.txt:ABC3  DEF3    GHI3    cond2/cond1
file1.txt:ABC4  DEF4    GHI4    cond2 cond1
file1.txt:ABC5  DEF5    GHI5    cond4/cond1
file1.txt:ABC9  DEF9    GHI9    cond1 at 50
file1.txt:ABCa  DEFa    GHIa    con cond1
file1.txt:ABCb  DEFb    GHIb    no. cond1
file1.txt:ABCc  DEFc    GHIc    cond1 something
file2.txt:col1  col2    col3    col4
file2.txt:ABC1  DEF1    GHI1    cond1
file2.txt:ABC6  DEF6    GHI6    cond1
file3.txt:col1  col2    col3    col4
file3.txt:ABC7  DEF7    GHI7    mcond1
file3.txt:ABC8  DEF8    GHI8    cond2
file3.txt:ABCc  DEFc    GHIc    Mcond1

或者,这里是单行:

awk -F "\t" 'NR==1 { r=$0; next } { i = ($4 == "cond1" ? 2 : ($4 ~ /cond1/ && $4 !~ /[Mm]cond1/ ? 1 : 3)); print (!a[i]++ ? r ORS : "") $0 > "file" i ".txt" }' file

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-01-16
    • 2013-01-26
    • 1970-01-01
    • 2012-05-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-24
    相关资源
    最近更新 更多