用 sed 命令替换长字符串:参数列表太长错误

用 sed 命令替换长字符串:参数列表太长错误

我正在尝试执行这个命令

sed -i -e "s/BASE_64/$BASE_64/" FILE_NAME

其中$BASE_64是文件内容的 Base 64 表示形式。

sed由于字符串太长,给我一个错误。

参数列表太长

如何才能避免这个错误呢?

答案1

你总是可以这样做(因为你sed已经在使用 GNU ( -i)):

sed -i -f - FILE_NAME << EOF
s/BASE_64/$BASE_64/g
EOF

-f -告诉sed从 stdin 读取 sed 脚本。

如果您想在 Linux(且仅限 Linux)上对多个文件重用相同的脚本,请使用类似于 的 shell zsh,版本高达 5.0 kshbash它使用临时文件实现此处文档(而不是像dashor yash(或bash5.1+)这样的管道相对较小的heredocs并且仍然使用GNU sed,你可以这样做:

find . -name '*.conf' -exec sed -i -f /dev/stdin {} + << EOF
s/BASE_64/$BASE_64/g
EOF

在 Linux 上(仅限 Linux 和 Cygwin),/dev/stdin并不意味着标准输入以同样的方式-。相反,它是指向在标准输入上打开的文件的符号链接,因此每次sed打开它时,它都会从头开始重新打开该文件。上面的命令在其他系统(具有/dev/stdin)或使用通过管道实现此处文档的 shell 上可以正常工作,但前提是只有足够少的conf文件sed仅被调用一次。当第二次调用时,在非 Linux/Cygwin 系统上,如 with -f -/dev/stdin将显示为空,因为它已被第一次调用读取。

busybox sed-i也以与 GNU 相同的方式支持sed,但不支持-f -.所以-f /dev/stdin无论如何你都想使用那里。对于 FreeBSD sed,使用:

sed -i '' -f /dev/stdin FILE_NAME << EOF
s/BASE_64/$BASE_64/g
EOF

答案2

首先,将 Base64 编码的数据保存在名为base64.txt.

例如:

base64 < originalfile > base64.txt

然后:

printf '%s\n' '/BASE64/r base64.txt' 1 '/BASE64/d' w | ed FILENAME

这用于ed搜索FILENAME包含字符串的行BASE64,在该行之后插入内容base64.txt,返回到第一行,然后BASE64再次搜索包含字符串的行并将其删除。该w命令ed保存修改后的文件。

答案3

另一种选择是将命令替换seded并将命令存储在文件中。例如,如果您ed_cmds使用以下内容创建:

%s/BASE_64/<expanded variable>/g
w
q

然后你可以运行

< ed_cmds ed FILE_NAME

它会进行您想要的更改,因此$BASE_64您无需进行设置,而是创建 ed 命令文件。

埃德解释

  • %表示将命令应用于文件的每一行
  • s/pat1/pat2/g在末尾替换出现的pat1pat2使其对线路上的每场比赛都执行此操作,而不仅仅是第一个g
  • w将更改写入磁盘
  • qquit (无论如何,当它得到 EOF 时就会发生)

当然,您也可以将sed命令放入文件中并使用-f,但如果您这样做并且想要就地修改文件,您最好使用ed而不是创建临时文件并移动它sed -i

答案4

我最终将sed说明放入文件中

SEDCOMMANDS=`tempfile`

并打电话给

sed -f "$SEDCOMMANDS" -- "$FILE_NAME"

如果你不使用的话也很好sed -i。如果您想就地编辑文件,请按照https://unix.stackexchange.com/a/284188/149867并将等效ed指令放入文件中,后跟wq

相关内容