如何通过匹配shell/bash脚本中的不同文件替换为for循环语句
在我的shell脚本中,我试图匹配2个不同的文件,并用File2的行替换File1中出现的内容:如何通过匹配shell/bash脚本中的不同文件替换为for循环语句,bash,shell,sed,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 ... File2-是一个格式化的“类似json”文件 实际上,脚本中必须使这项工作看起来像 IFS=$'\n' set -f for i in $(cat < File2
File1 occurency 1 <-- File2 row 1
File1 occurency 2 <-- File2 row 2
File1 occurency 3 <-- File2 row 3
...
File2-是一个格式化的“类似json”文件
实际上,脚本中必须使这项工作看起来像
IFS=$'\n'
set -f
for i in $(cat < File2.txt); do
sed -i "s|.*social.*|$i|g" File1.json
done
我需要这样的输出
...
"@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",
...
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
提前感谢您的帮助。编辑:
在仔细查看了您想要的输出之后,我得出了这个结论
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 in place,那么您将不得不这样做
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
所以整件事看起来是这样的
...
"@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",
...
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
这可能适用于您(GNU-sed):
这将用文件2中的一行替换包含的每一行xxxxxxx.jpg
。谢谢大家
在检查了@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循环来完成,但即使这样对我来说也没关系。
谢谢你
给我美元(cat
写得更好;做完成s
命令的右侧将导致输出中出现文字星号,我怀疑这是OP想要的。我想他用星号来强调。谢谢,鹅,但是你的解决方案不起作用。在第一个循环中,它仍然覆盖所有occorence,因此在第二个循环中,它找不到更多“*social.*”我发现了这种命令,我试图将其应用到我的代码sed-i“0,/name:/{s/name:.*/name:${NEW_VALUE}/}”。/myFile
@AlexandrMisiyuk我更新了我的代码,我认为这更像您正在寻找的代码。我吸取了教训,我会更加注意阅读期望的输出。@Dennis Williamson你完全正确,这就是我略读的结果。那太简单了我应该知道你用的是什么版本的awk?我不知道有哪一个支持-I
。以便就地修改文件。该选项至少在GNU awk中有一个。注意:这是对完整for循环的替换。我尝试执行它,结果是它删除了File1Damn it中的整行!对于某种奇怪的错误,它不会更有效。。。如果启动bash脚本,“AWK”命令将不会执行。。我有带AWK3的Linux6,它不支持就地替换。
sed -e '/xxxxxxx\.jpg/R file2' -e '//d' file1
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