macos - 为什么这些简单的 shell 命令在 sed 的替换部分中使用时会失败

标签 macos bash shell sed awk

试图找到 this sed question 的答案时 我想到了一个我无法理解的奇怪行为。

假设我有一个名为 data

的文件
$> cat data
foo.png
abCd.png
bar.png
baZ.png

任务是在行中使用 sed 将所有具有大写 ASCII 字符的行替换为小写。所以输出应该是:

$> cat data
foo.png
abcd.png
bar.png
baz.png

该解决方案应该在非 gnu sed 上也能像 Mac 上的 sed 一样工作

我尝试将这个嵌入式 awk 嵌入到 sed 的替换部分:

sed -E 's/[^ ]*[A-Z][^ ]*.png/'$(echo \&|awk '{printf("<%s>[%s]",$0, tolower($0))}')'/' data

奇怪的是,输出是这样的:

foo.png
<abCd.png>[abCd.png]
bar.png
<baZ.png>[baZ.png]

正如您所看到的,sed 正在使用大写字母选择正确的行,这也影响到 awk,但是 awk 的 tolower() 函数失败并生成与输入相同的文本。

请 shell 专家解释一下这种奇怪的行为。

最佳答案

你的 awk命令在 sed 之前运行命令,而不是 sed 的子进程命令,所以 awk仅接收一个文字符号作为输入,结果输出

<&>[&]

此字符串然后嵌入到 sed 的字符串中receives 作为它的参数,从中应该很明显为什么 sed产生它所做的输出。

事件的顺序是

  1. shell 看到这个命令行

    sed -E 's/[^ ]*[A-Z][^ ]*.png/'$(echo \&|awk '{printf("<%s>[%s]",$0, tolower($0))}')'/' data
    
  2. 它处理命令替换(其中 awk& 变成 <&>[&] ),以生成中间命令行

    sed -E 's/[^ ]*[A-Z][^ ]*.png/'<&>[&]'/' data
    
  3. 然后 shell 执行 sed使用命令 s/[^ ]*[A-Z][^ ]*.png/<&>[&]/

关于macos - 为什么这些简单的 shell 命令在 sed 的替换部分中使用时会失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16673265/

相关文章:

linux - 陷阱在 linux 脚本中不捕获退出代码

regex - 如何在我的整个系统中进行查找和替换?

java - 转储 keystore 内容 : Permission denied keytool java_cacerts

php - 为什么这个 CURL 在 PHP 中有效但在 shell 中无效

macos - 如何在mac中设置默认WIFI网络?

macos - brew install docker 不包括 docker 引擎?

android - ro.boot.serialno 和 ro.serialno 存储在哪里?

linux - 连接到 docker 容器中的特定 shell 实例?

apache-flex - 错误 #3219 AIR 中的 NativeProcess

macos - C++、OS X 的 clang 与 GCC 中的 Lambda 表达式