sed:多个 -e 或 while 循环?

sed:多个 -e 或 while 循环?

我有一个包含值元组的 CSV 文件,我需要在不同的(大)文件中将一个值的出现次数更改为另一个值的出现次数。

到目前为止,我已经完成了一段时间的 read line [...] < foo.csv,实质上是为 CSV 文件中的每一行运行 sed 一次。

这需要相当长的时间,所以我想知道是否应该更改 while 循环来构造一个很长的多个 -e 语句字符串,然后使用 eval 运行它。

显然,我可以尝试,但如果有人可以告诉我 sed 本质上是否会执行与我迄今为止所做的相同的操作,即为每个 -e 语句运行文件,这意味着不会获得任何性能增益,那么我想我不会打扰。

评论后编辑:

基本上,我执行以下操作:

while read line
do
  old_user=echo $line | cut -d \; -f 2|tr -d \"
  new_user=echo $line | cut -d \; -f 4|tr -d \"

  if [ "$old_user" != "$new_user" ]
  then
    sed -i -e "s/^(.*ri:username=\")$old_user(\".*)$/\1$new_user\2/g" confluence/entities_converted.xml
  fi
done < usernames.csv

如果您注意到它是一个 XML 文件,原因是在很多情况下 XML 解析和重写很麻烦,因此sed.我只是想知道,我是否应该构造多个参数,而不是sed多次运行。-esed

usernames.csv好像

    "Full name";"Username";"Email";"New username"
    "Sune Mølgaard";"sune.molgaard";"[email protected]";"smo"

沿着第二条线的路径可以有任意数量的线,因此是循环的。我知道第一行可能不匹配,但这无关紧要。

答案1

无需评估或构造多个 -e。 Sed 可以从文件或管道中读取其“程序”,您实际上也可以在 sed 中生成该“程序”:

cut -f2,4 -d\; usernames.csv \
    | sed -e 's/^/s%ri:username=/' -e 's/;/%ri:username=/' -e 's/$/%/' \
    | sed -i~ -f- confluence/entities_converted.xml

要检查生成的程序,请删除最后一行。

如果您想跳过不需要更改的行(可能会加快速度),请通过grep在 sed 之间插入来删除它们:

   | grep -v '"\(.*\)".*"\1"' \

答案2

您应该使用 awk 解析 usernames.csv (其中字段 2 和 4 不同),并生成 sed 文件。

 tr -d \" username.csv |
 awk -F\; '$2 != $4 { printf "s/^(.*ri:username=%c)%s(%c.*)$/\\1%s\\2/g\n",34,$2,34,$4 ; }' |
 sed -i -f - confluence/entities_converted.xml

一些技巧

  • 使用 printf "..%c..",34 生成引号。
  • 您可以跳过调试部分中的 sed 行,以确保正确生成所有 sed 指令。
  • 你需要/g替代吗?

在我的测试文件上

;foo;;foo;;
;fubar;;mr X;;
;bar;;bistro;;
    "Full name";"Username";"Email";"New username"
    "Sune Mølgaard";"sune.molgaard";"[email protected]";"smo"

这产生

s/^(.*ri:username=")fubar(".*)$/\1mr X\2/g
s/^(.*ri:username=")bar(".*)$/\1bistro\2/g
s/^(.*ri:username=")Username(".*)$/\1New username\2/g
s/^(.*ri:username=")sune.molgaard(".*)$/\1smo\2/g

不要费心删除用户名这一行,如果找不到,则无法替代。

相关内容