10

我想将匹配结果的特定部分存储为变量,以供以后替换。我想把它放在一个衬里,而不是事先找到我需要的变量。

在配置 apache 并使用 mod_rewrite 时,您可以指定要用作变量的模式的特定部分,如下所示:

RewriteRule ^www.example.com/page/(.*)$ http://www.example.com/page.php?page=$1 [R=301,L]

括号内包含的模式匹配部分存储为 $1 以供以后使用。因此,如果 url 是www.example.com/page/home,它将被替换为www.example.com/page.php?page=home。因此,匹配的“home”部分保存在 $1 中,因为它是括号内的模式部分。

我想要一个类似这个功能的sed命令,我需要自动替换 SQL 转储文件中的许多字符串,在每个创建表之前添加删除表(如果存在)命令,但我需要知道表名才能做到这一点,所以如果转储文件包含以下内容:

...
CREATE TABLE `orders`
...

我需要运行类似的东西:

cat dump.sql | sed "s/CREATE TABLE `(.*)`/DROP TABLE IF EXISTS $1\N CREATE TABLE `$1`/g"

得到结果:

...
DROP TABLE IF EXISTS `orders`
CREATE TABLE `orders`
...

我在sed命令中使用 mod_rewrite 语法作为我正在尝试做的逻辑示例。

有什么建议么?

4

4 回答 4

13
sed '/CREATE TABLE \([^ ]*\)/ s//DROP TABLE IF EXISTS \1; &/'

查找 CREATE TABLE 语句并捕获表名。将其替换为 'DROP TABLE IF EXISTS' 和表名,加上一个分号来终止语句,以及匹配的内容的副本以保留 CREATE TABLE 语句。

这是经典的sed符号。由于您使用bash的是 GNU,因此您可能会使用 GNUsed并且需要添加--posix以使用该表示法,或者您需要修改脚本以使用 GNU 的非标准正则sed表达式。我也没有尝试在输出中插入换行符。sed如果它对您来说足够重要,您可以使用 GNU 来做到这一点。

关键点是括号(通常需要用反斜杠转义)是捕获机制,反斜杠编号是替换机制。

于 2012-10-15T15:39:20.510 回答
6
 sed -r "s/CREATE TABLE (\`.*\`)/DROP TABLE IF EXISTS \1\n &/g" dump.sql

测试

kent$  cat t.txt

CREATE TABLE `orders`
...

CREATE TABLE `foo`
...
...

CREATE TABLE `bar`
...


kent$  sed -r "s/CREATE TABLE (\`.*\`)/DROP TABLE IF EXISTS \1\n &/g" t.txt

DROP TABLE IF EXISTS `orders`
 CREATE TABLE `orders`
...

DROP TABLE IF EXISTS `foo`
 CREATE TABLE `foo`
...
...

DROP TABLE IF EXISTS `bar`
 CREATE TABLE `bar`
...
于 2012-10-15T15:42:36.357 回答
5

这称为“反向引用”。sed 将开始对括号之间的内容进行编号。\(...\)

请注意上面使用反斜杠作为转义字符。

参考:https ://www.gnu.org/software/sed/manual/html_node/Regular-Expressions.html

于 2016-02-26T17:18:00.203 回答
0

这是通过该线程标题对OP问题的回答:正如@bhoom-suktitipat所说:这被称为“反向引用”......

摘要:在替换端,通过使用反斜杠后跟一个数字(从 1 开始)来实现占位符变量或反向引用查找,如下所示:\1

背景:我来这里是因为我一直在使用一堆代码并对其进行修改。在此过程中,我想预先对其进行 eslint 以查找 JSON 键周围的所有双引号并将它们剥离。ESLint 的 Quote Props Rule可以与 --fix 一起使用,来做与我需要做的完全相反的事情。

任务大纲:

变成 { "foo": "bar" }{ foo: "bar" }也就是using-placeholders-variables-in-a-sed-command

  1. 在第二个匹配组中找到“foo”(键)的等价物:("{1})(\w+)(":{1})
  2. 使用该匹配组作为占位符来呈现foo:,而不是"foo":
  3. 将更改写入文件。

写入不同的文件:

sed -r 's/("{1})(\w+)(":{1})/\2:/g' in.js > out.js

写入同一文件:

sed -ri 's/("{1})(\w+)(":{1})/\2:/g' in-and-out.js

使用的 SED 标志:

-E, -r, --regexp-extended use extended regular expressions in the script (for portability use POSIX -E).

-i[SUFFIX], --in-place[=SUFFIX] edit files in place (makes backup if SUFFIX supplied)

于 2019-10-07T14:08:59.413 回答