【问题标题】:File Search in LINUXLINUX 中的文件搜索
【发布时间】:2021-11-13 12:06:47
【问题描述】:

我有两个文件,FILE1 包含很多行,FILE2 包含 KEY VALUE 参数。我需要将FILE2FILE1 进行比较,如果匹配,则FILE1 中的相应单词应替换为FILE2 中的下一列。

例子:

文件1:

<SOME YAML CODE
-------------->
PARM1
value:PARM2
PARM3
somyaml_PARM4
<END OF YAML CODE
---------------->

文件2:

PARM1 mmddyy
PARM2 hhmmss
PARM3 awsid
PARM4 cc

因此,对于FILE1 中来自FILE2 的每个匹配项,FILE1 中的相应单词应替换为FILE2 中的第二列。所以所需的输出应该是:

<SOME YAML CODE
-------------->
**mmddyy**
value:**hhmmss**
**awsid**
somyaml_**cc**
<END OF YAML CODE
---------------->

在其他社区的帮助下,我能够在命令下运行,但它仅在搜索条件位于行首时才有效

awk '
    NR==FNR{k[$1]=$2;}
    NR!=FNR{if($1 in k){$0=k[$1]};print}
' file2 file1

【问题讨论】:

  • 请正确格式化您的问题。提示:试试{} 按钮。
  • 另外请注意,您需要一个 YAML 解析器,因为基于 Regex 的 shell 工具都不适合处理复杂的数据结构,例如 YAML、JSON、XML/HTML/SGML……解析如 Python、Ruby、Perl……
  • 执行示例中显示的操作很简单。如果您的某些 PARM 可能是其他 PARM 的子集(例如 PARM2 在 file2 但 PARM20 在 file1 中)或包含正则表达式元字符,或者 PARM2 的第二个字段包含 &amp; 或其他反向引用,则执行我认为您想要的字符串会更难。因此,如果任何一种情况都可能发生,那么不要仅仅发布一个微不足道的晴天案例,其中一切都是唯一的、不相关的字母数字字符串,edit 你的问题是提供一个示例,该示例将是对潜在解决方案的真实测试.

标签: python bash shell awk


【解决方案1】:

这个awk 应该适用于您的示例数据。

$ awk -F"[ :_]" 'NR==FNR {array[$1]=$2; next} $1~/PARM/{sub(/PARM./,array[$1])}$2~/PARM/{sub(/PARM./,array[$2])}1' file2 file1
$ cat awk.script
#!/usr/bin/env awk -f

BEGIN {
    FS="[ :_]"                           #Set the delimiters to use
} NR==FNR {                              
    array[$1]=$2                         #Create array from file2
    next                                 #Move to file1
} $1~/PARM/ {                            #If column1 matches PARM
    sub(/PARM./,array[$1])               #Substitute PARM for content of array
} $2~/PARM/ {                            #If column 2 matches PARM
    sub(/PARM./,array[$2])               #Substitute PARM for content array
} 1                                      #Print

输出

$ awk -f awk.script file2 file1
<SOME YAML CODE
-------------->
mmddyy
value:hhmmss
awsid
somyaml_cc
<END OF YAML CODE
---------------->

【讨论】:

    【解决方案2】:

    即使您的 PARM 值是其他 PARM 值的子集,或者包含正则表达式元字符的 PARM 或包含反向引用或递归定义的替换字符串(其中 PARM1 映射到 PARM2,PARM2 映射到 PARM1),这也可以满足您的需求。如果 file2 定义了一个 PARM 到另一个 PARM 的映射,那么这只是按照最长优先顺序进行映射。它使用 GNU awk 进行 sorted_in,因此我们可以按最长优先顺序访问 PARM 以正确处理子集 - 如果您没有 GNU awk,则在 awk 脚本之外执行 file2 的排序。

    $ cat tst.awk
    BEGIN {
        PROCINFO["sorted_in"] = "@val_num_desc"
    }
    NR==FNR {
        map[$1] = $2
        len[$1] = length($1)
        next
    }
    {
        for ( old in len ) {
            new = map[old]
            head = ""
            tail = $0
            while ( s=index(tail,old) ) {
                head = head substr($0,1,s-1) new
                tail = substr(tail,s+len[old])
            }
            $0 = head tail
        }
        print
    }
    

    $ awk -f tst.awk file2 file1
    <SOME YAML CODE
    -------------->
    mmddyy
    value:hhmmss
    awsid
    somyaml_cc
    <END OF YAML CODE
    ---------------->
    

    问题中提供的示例并不好,因为它仅涵盖最基本的晴天情况,其中 file2 中的所有字符串都是唯一的并且仅由字母数字字符组成。更好的测试在第一个字符串中使用正则表达式元字符、作为其他字符串子集的字符串以及在替换字符串中使用反向引用元字符,例如:

    $ head file1 file2
    ==> file1 <==
    <SOME YAML CODE
    -------------->
    A.B
    value:A.BX
    PARM3
    somyaml_PARM4
    <END OF YAML CODE
    ---------------->
    
    ==> file2 <==
    A.B mmddyy
    A.BX hhmmss
    PARM3 a\1b&c
    PARM4 cc
    

    $ awk -f tst.awk file2 file1
    <SOME YAML CODE
    -------------->
    mmddyy
    value:hhmmss
    a\1b&c
    somyaml_cc
    <END OF YAML CODE
    ---------------->
    

    这仍然缺少需要考虑的案例,例如其中 file2 包含递归映射,甚至只是从一个“PARM”字符串到另一个的一次性映射:

    $ head file1 file2
    ==> file1 <==
    <SOME YAML CODE
    -------------->
    PARM1
    value:PARM2
    PARM3
    somyaml_PARM4
    <END OF YAML CODE
    ---------------->
    
    ==> file2 <==
    PARM1 mmddyy
    PARM2 hhmmss
    PARM3 PARM4
    PARM4 PARM3
    

    $ awk -f tst.awk file2 file1
    <SOME YAML CODE
    -------------->
    mmddyy
    value:hhmmss
    PARM4
    somyaml_PARM4
    <END OF YAML CODE
    ---------------->
    

    但这没有在问题中讨论,所以我不知道这是否是预期的输出,如果不是,预期的输出会是什么以及为什么 - 如果您需要处理该问题或任何问题,请更新问题其他不平凡的案例则不同。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-02-24
      • 2021-08-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多