如何通过在shell / bash脚本中匹配不同的文件来替换for循环语句

时间:2019-05-28 22:28:16

标签: bash shell sed

使用我的shell脚本,我试图匹配2个不同的文件,并用File2的行替换File1中的出现情况:

File1 occurency 1 <-- File2 row 1
File1 occurency 2 <-- File2 row 2
File1 occurency 3 <-- File2 row 3
...

文件2中的行数等于文件1中的发生率,因为最初它们是从文件1中获取的

File1-是Json文件

...
"@type" : "Review",
"@id":"https://google.com/social/profile/xxxxxxx.jpg"
"datePublished" : "Tue Sep 18 16:32:53 CEST 2012",

"@type" : "Review",
"@id":"https://google.com/social/profile/xxxxxxx.jpg"
"datePublished" : "Tue Sep 18 16:32:53 CEST 2012",
 ...

File2-是格式化的“类似于json”文件

"profilePhoto":"https://someurl.ltd/aaaa_90.jpg"
"profilePhoto":"https://someurl.ltd/bbbb_90.jpg"
"profilePhoto":"https://someurl.ltd/cccc_90.jpg"
 ....

实际上,脚本必须完成这项工作的部分是

IFS=$'\n'
set -f
for i in $(cat < File2.txt); do

sed -i "s|.*social.*|$i|g" File1.json

done

此脚本用File2的第一行替换File1中的所有匹配项,因此在第二个循环中没有更多的匹配要查找。 输出示例

...
"@type" : "Review",
"profilePhoto":"https://someurl.ltd/cccc_90.jpg"
"datePublished" : "Tue Sep 18 16:32:53 CEST 2012",

"@type" : "Review",
"profilePhoto":"https://someurl.ltd/cccc_90.jpg"
"datePublished" : "Tue Sep 18 16:32:53 CEST 2012",
 ...

我需要这样的输出

...
"@type" : "Review",
*"profilePhoto":"https://someurl.ltd/**aaaa**_90.jpg"*
"datePublished" : "Tue Sep 18 16:32:53 CEST 2012",

"@type" : "Review",
*"profilePhoto":"https://someurl.ltd/**bbbb**_90.jpg"*
"datePublished" : "Tue Sep 18 16:32:53 CEST 2012",
 ...

在此先感谢您的帮助。

3 个答案:

答案 0 :(得分:1)

编辑:

仔细检查您想要的输出之后,我想到了这个

for i in $(sed 's/^/*/;s|ltd/|&**|;s|_|**&|;s/$/*/' File2.txt); do awk -i inplace -v i="$i" 'NR==1,/.*social.*/{sub(/.*social.*/, i)} 1' File1.json; done

一旦您将File1.json中的替换限制为仅第一次出现,就可以让循环为您工作。

要分解

# Instead of cat file I tackled substitution for each line in File2.txt as $i
for i in $(sed 's/^/*/;s|ltd/|&**|;s|_|**&|;s/$/*/' File2.txt); do

    # Here awk sub only first occurrence to not overwrite whole file
    # Second loop will handle the next occurrence with second line from File2.txt  
    # And third ect.. ect..
    awk -i inplace -v i="$i" 'NR==1,/.*social.*/{sub(/.*social.*/, i)} 1' File1.json
done     

以下所有内容是如果您的awk版本不支持-i inplace,那么您将必须这样做

awk -v i="$i" 'NR==1,/.*social.*/{sub(/.*social.*/, i)} 1 { rec = rec $0 RS } END { close(FILENAME); printf "%s", rec > FILENAME }' File1.json

所以整个事情看起来像

 # Instead of cat file I tackled substitution for each line in File2.txt as $i
for i in $(sed 's/^/*/;s|ltd/|&**|;s|_|**&|;s/$/*/' File2.txt); do

    # Here awk sub only first occurrence to not overwrite whole file
    # Second loop will handle the next occurrence with second line from File2.txt  
    # And third ect.. ect..
    awk -v i="$i" 'NR==1,/.*social.*/{sub(/.*social.*/, i)} 1 { rec = rec $0 RS } END { close(FILENAME); printf "%s", rec > FILENAME }' File1.json
done

最后,如果以上awk命令都不起作用,则可以生成临时文件。

awk -v i="$i" 'NR==1,/.*social.*/{sub(/.*social.*/, i)} 1' File1.json > tmpfile && mv tmpfile File1.json

所以整个事情看起来像这样

for i in `cat File2.txt`; do

 awk -v i="$i" 'NR==1,/.*social.*/{sub(/.*social.*/, i)} 1' File1.json > tmpfile && mv tmpfile File1.json

done

答案 1 :(得分:1)

这可能对您有用(GNU sed):

sed -e '/xxxxxxx\.jpg/R file2' -e '//d' file1

这会用file2中的一行替换包含xxxxxxx.jpg的每一行。

答案 2 :(得分:0)

谢谢大家!

在检查了@goose的建议之后,我做了一点改动 解决该问题的最终解决方案是

for i in `cat jsonlike.txt`; do

awk -v i="$i" 'NR==1,/.*social.*/{sub(/.*social.*/, i)} 1 { rec = rec $0 RS } END { close(FILENAME); printf "%s", rec > FILENAME }' File1.json

done

我知道也可以使用while循环来完成,但是即使这样对我也可以。 谢谢