shell awk -仅通过第一次出现的分隔符替换和拆分模式

ct3nt3jp  于 2023-10-23  发布在  Shell
关注(0)|答案(6)|浏览(170)

我有2个文件,想根据这2个文件(testfile 1和2)创建一个新文件。通过从testfile1.txt中逐行阅读第一个文件,并根据testfile2.txt中特殊字符@和其值之间的字符串匹配。更多细节见下文。
testfile1.txt

## START :: start of file ##
[email protected]_path@
#
pa[email protected]_brkr_path@
#
[email protected]_path@
#
path.mw.site[email protected]_brkr_path@
## END :: end of file ##

testfile2.txt

mysite.mw_path=/mw/mysite/cfg/DATA1/
mysite.mw_brkr_path=/usr/local/mw/mysite/cfg/DATA2/=/mydirectory/

这是我的命令

awk 'FNR==NR{a[$1]=$2; next} match($0, "@[^@]*@"){
        i=substr($0, RSTART+1, RLENGTH-2 "@");
        gsub("@"i"@", a[i]);  }1 ' FS== testfile2.txt testfile1.txt
## START :: start of file ##
path.mw.site.profiles=/mw/mysite/cfg/DATA1/
#
path.mw.site.broker.profiles=/usr/local/mw/mysite/cfg/DATA2/
#
path.mw.site.profiles=/mw/mysite/cfg/DATA1/
#
path.mw.site.broker.profiles=/usr/local/mw/mysite/cfg/DATA2/
## END :: end of file ##

我得到了上面的输出。我期待输出如下。

## START :: start of file ##
path.mw.site.profiles=/mw/mysite/cfg/DATA1/
#
path.mw.site.broker.profiles=/usr/local/mw/mysite/cfg/DATA2/=/mydirectory/
#
path.mw.site.profiles=/mw/mysite/cfg/DATA1/
#
path.mw.site.broker.profiles=/usr/local/mw/mysite/cfg/DATA2/=/mydirectory/
## END :: end of file ##

先谢了。

0qx6xfy6

0qx6xfy61#

awk -F@ -v OFS= '
    # process the substitution table
    NR==FNR {
        # if it looks like a key/value pair, save it
        if (i=index($0,"="))
            a[ substr($0,1,i-1) ] = substr($0,i+1)
        # else warn about invalid line

        next
    }

    # process the template
    {
        # line has been split into fields on "@"
        # "@" come as pairs, so even fields are keys

        # warn if NF%2 != 0

        # do the substitutions
        # undefined keys are replaced with ""
        # check key exists if that is not wanted
        for (i=2; i<=NF; i+=2)
            $i=a[$i]

        print
    }
' testfile2.txt testfile1.txt
iswrvxsc

iswrvxsc2#

不要在 every=字符处拆分输入,而是以不同的方式提取键和值。
可能的解决办法(除其他外)

awk 'FNR==NR{key=val=$0;sub(/=.*/,"",key);sub(/[^=]*=/,"",val);a[key]=val; next}
match($0, "@[^@]*@"){
        i=substr($0, RSTART+1, RLENGTH-2 "@");
        gsub("@"i"@", a[i]);  }1 ' testfile2.txt testfile1.txt
mkshixfv

mkshixfv3#

文件分隔符FS设置为=testfile2.txt 有2个等号,这就是为什么您在输出中缺少第三部分,因为您只使用$2
你可以做的是删除FS==,因为你不需要 testfile1.txt,并在一个更具体的字符串_path=上分割 testfile2.txt

awk 'FNR==NR{
  split($0, p, "_path=")
  a[p[1] "_path"] = p[2]
  next
} 
match($0, "@[^@]*@"){
  i = substr($0, RSTART+1, RLENGTH-2 "@");
  gsub("@"i"@", a[i]);  
}1 ' testfile2.txt testfile1.txt

输出

# START :: start of file ##
path.mw.site.profiles=/mw/mysite/cfg/DATA1/
#
path.mw.site.broker.profiles=/usr/local/mw/mysite/cfg/DATA2/=/mydirectory/
#
path.mw.site.profiles=/mw/mysite/cfg/DATA1/
#
path.mw.site.broker.profiles=/usr/local/mw/mysite/cfg/DATA2/=/mydirectory/
## END :: end of file ##
tvokkenx

tvokkenx4#

假设条件:

  • 如果@some_pattern_to_match@不匹配,则保持原样

testfile1.txt添加一个不匹配的条目(请参阅最后一行旁边的内容):

$ cat testfile1.txt
## START :: start of file ##
[email protected]_path@
#
[email protected]_brkr_path@
#
[email protected]_path@
#
[email protected]_brkr_path@
#
path.mw.[email protected]_MATCH@
## END :: end of file ##

awk

awk '
FNR==NR { if ( n=index($0,"=") )                        # 1st file: if line includes a "=" then ...
             a[ substr($0,1,n-1) ] = substr($0,n+1)     # split and save as array index and value
          next
        }

# 2nd file: split on "@" and if we get 3 fields and the 2nd field is an index in array a[] then rewrite current line

split($0,x,"@")==3 && x[2] in a { $0 = x[1] a[x[2]] }

1                                                       # 2nd file: print current line
' testfile2.txt testfile1.txt

这产生:

## START :: start of file ##
path.mw.site.profiles=/mw/mysite/cfg/DATA1/
#
path.mw.site.broker.profiles=/usr/local/mw/mysite/cfg/DATA2/=/mydirectory/
#
path.mw.site.profiles=/mw/mysite/cfg/DATA1/
#
path.mw.site.broker.profiles=/usr/local/mw/mysite/cfg/DATA2/=/mydirectory/
#
path.mw.[email protected]_MATCH@
## END :: end of file ##
b4qexyjb

b4qexyjb5#

为什么不使用sed

sed 's/=/@^/; s/^/s^@/; s/$/^g/' testfile2.txt | sed -f- testfile1.txt

输出量:

## START :: start of file ##
path.mw.site.profiles=/mw/mysite/cfg/DATA1/
#
path.mw.site.broker.profiles=/usr/local/mw/mysite/cfg/DATA2/=/mydirectory/
#
path.mw.site.profiles=/mw/mysite/cfg/DATA1/
#
path.mw.site.broker.profiles=/usr/local/mw/mysite/cfg/DATA2/=/mydirectory/
## END :: end of file ##
qvsjd97n

qvsjd97n6#

$ awk -F'=' -v OFS='=' '
       NR==FNR{
               key="@"$1"@"; 
               sub(/^[^=]*=/,""); 
               a[key]=$0; 
               next
       } 
       $2 in a { $2=a[$2] }1
' testfile2.txt testfile1.txt 

## START :: start of file ##
path.mw.site.profiles=/mw/mysite/cfg/DATA1/
#
path.mw.site.broker.profiles=/usr/local/mw/mysite/cfg/DATA2/=/mydirectory/
#
path.mw.site.profiles=/mw/mysite/cfg/DATA1/
#
path.mw.site.broker.profiles=/usr/local/mw/mysite/cfg/DATA2/=/mydirectory/
## END :: end of file ##

相关问题