有人能解释一下这个sed
命令是如何工作的吗?
sed 's@+@ @g;s@%@\\x@g' | xargs -0 printf "%b"
答案1
在 sed 中,替换命令通常写为s/pattern/replacement/options
。但是,没有必要使用/
- 如果方便的话,您可以使用其他字符,因此可以是s@pattern@replacement@options
或s:foo:bar:g
。s@+@ @g
就像s/+/ /g
-+
用空格替换所有内容。同样,s@%@\\x@g
用 替换所有%
内容\x
(单个反斜杠在 sed 中是转义字符,因此您需要两个才能获得真正的反斜杠)。
像 这样的字符串foo+%2Fbar
将变成foo \x2Fbar
。printf "%b"
将扩展反斜杠转义序列,如\x2F
(十六进制值为 2F 的 ASCII 字符,即/
),最终得到foo /bar
。
答案2
您要询问的用于解码URL 中的+
es 和序列的命令%
不仅仅是一个sed
命令,它还是一个管道处理输入sed
,然后将其传输到xargs
进行进一步处理。首先让我们看一下sed
命令:
sed 's@+@ @g;s@%@\\x@g'
您可能更习惯于将它与/
而不是@
分隔符一起使用,这在这里很容易做到,而且不会造成任何复杂情况,因为/
它既不出现在搜索模式中,也不出现在替换文本中。此命令等效于:
sed 's/+/ /g;s/%/\\x/g'
例如/
,@
就是 的一个非常好的标点符号sed
。
在每一行输入中:
s@+@ @g
(s/+/ /g
) 将 (s
) 个出现的 替换为+
空格。这会影响+
行 (g
) 上的所有 es,而不仅仅是第一个。;
结束操作(“命令”)并允许您在同一个“脚本”中指定另一个操作。s@%@\\x@g
(s/%/\\x/g
) 将 (s
) 次出现的%
替换为\x
。与前面一样,它作用于所有行,而不仅仅是每行的第一行 (g
)。在 中
\\x
仅\\
表示一个,\
因为\
对 有特殊含义sed
。它的特殊含义实际上是您用来消除其后另一个字符的特殊含义的字符,否则该字符将具有特殊含义。因此必须将其转义为\\
。
现在让我们看一下该xargs
命令,其目的是运行printf
。
xargs
构造命令行。如果您运行,其中xargs command...
command...
是一个或多个单词,xargs
运行command...
附加命令行参数从其输入读取。在本例中,由于管道 ( ),的输入xargs
是 的输出。通常将其输入中的任何空格解释为意味着它之前和之后的文本构成单独的参数,但sed
|
xargs
-0
选项使其在出现空字符反而。
在命令的预期用途中,不会出现空字符并且只需一个额外的命令行参数xargs
即可运行,即printf %b
sed
。因此,虽然一般来说并不等同,但在这种情况下,整个管道可能应该像这样编写:命令替换代替xargs
:
printf '%b\n' "$(sed 's/+/ /g;s/%/\\x/g')"
至于printf
这里要做什么,正如穆鲁所说格式%b
说明符使用并打印一个参数(如%s
),但会导致反斜杠转义(sed
管道左侧的命令被编写为生成反斜杠转义)翻译成他们所代表的角色。
假设我运行该命令并将其http://foldoc.org/debugging%20by%20printf
作为输入传递。我得到了http://foldoc.org/debugging by printf
输出,因为%20
序列被翻译成了空格。
答案3
这就是 的美妙之处sed
,它将其范例应用于自身...在命令(例如s
或tr
或无)之后,下一个字符被视为分隔符。
您应该明智地选择,以避免干扰 shell 和命令本身,并保持内容可读,但编写如下可怕的内容是完全有效的:
echo 'arrival' | sed srarbrg
...并得到brrivbl
结果,这正是您所期望的。您可以尽情地让它变得非常神秘,例如:
echo 'arrival' | sed s\fa\fb\fg # \f is form feed, chr(12)
常见的用法是使用斜线作为分隔符,但是当您的表达式包含分隔符时,可以更轻松地了解意图。您的分隔符可以是 ASCII8 范围内的任何值(多字节分隔符,例如£
引发错误)。
只要记住目标是让事情变得更容易,而不是更神秘。