【问题标题】:How do I search and replace a string in multiple ZIP files?如何在多个 ZIP 文件中搜索和替换字符串?
【发布时间】:2014-02-21 05:31:51
【问题描述】:

我在找到正确的命令来搜索和查找包含 Unix 上的 XML 文件的多个 ZIP 文件中的字符串时遇到问题。

我能够在多个 ZIP 文件中找到一个搜索字符串,但未能成功替换该查找并替换该字符串。

不幸的是,这不太奏效。一旦找到解压缩文件的字符串(到临时位置),我正在尝试使用 grep 和 sed 命令。但我可能不正确地假设我可以编辑到临时?

oldAddress='<ns1:line1/>'
newAddress='<ns1:line1>somestring</ns1:line1>'

for file in *.zip; do
    unzip -c "$file" | grep -q "<ns1:line1/>" | xargs -l {} sed -i 's/$oldAddress/$newAddress/g'
done

提前致谢。

【问题讨论】:

  • sed 周围的单引号将阻止变量插值。

标签: bash shell unix sed grep


【解决方案1】:

关于循环结构的几点说明:

首先,虽然使用全局变量很诱人,但 bash 还支持以下循环样式:

 while read line ; do   echo $line; done < <(find . -iname 'file*zip')

其次,您可以使用zipgrep搜索文件,然后只解压缩真正需要解压缩的文件。这将导致文件的两次紧缩。一次用于greping,一次用于解压缩真正需要解压缩的人。但是,这将使我们无需将多余的文件压缩回去。

第三,你正在搜索 2 次,对于大文件或许多文件,这将慢两倍:

 grep -q "<ns1:line1/>" | xargs -l {} sed -i 's/$oldAddress/$newAddress/g'

相反,您可以仅解压缩那些匹配的文件,并仅使用 sed 一步完成搜索和替换。

建议的解决方案

# From within a (bash) script you need to use double quotes instead of singel qoutes to expand the variable
newAddress="<ns1:line1>somestring</ns1:line1>"
oldAddress="<ns1:line1/>"

for fname in *.zip
do
  zipgrep -q $oldAddress $fname;    
  if [ $? -eq 0 ]; then
     filename="${fname%.*}" 
     unzip -qp $fname | sed -e 's#'$oldAddress'#'$newAddress'#g' > $filename
     zip $filename.zip $filename
  fi
done

测试数据

这是一个创建测试数据的for循环:

for i in {1..4} ; do touch file$i; done
while read line ; do   
  echo '<ns1:line1/>' > $line;   
  zip $line.zip $line
  rm $line
done < <(find . -iname 'file*')

【讨论】:

    猜你喜欢
    • 2018-01-02
    • 2020-05-12
    • 1970-01-01
    • 2018-07-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-22
    • 1970-01-01
    相关资源
    最近更新 更多