bash 在 sed 命令中使用占位符/变量

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12898945/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 03:32:51  来源:igfitidea点击:

Using placeholders/variables in a sed command

bashsedawk

提问by jesse_galley

I want to store a specific part of a matched result as a variable to be used for replacement later. I would like to keep this in a one liner instead of finding the variable I need before hand.

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

when configuring apache, and use mod_rewrite, you can specificy specific parts of patterns to be used as variables,like this:

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

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

the part of the pattern match that's contained inside the parenthesis is stored as $1 for use later. So if the url was www.example.com/page/home, it would be replaced with www.example.com/page.php?page=home. So the "home" part of the match was saved in $1 because it was the part of the pattern inside the parenthesis.

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

I want something like this functionality with a sedcommand, I need to automatically replace many strings in a SQL dump file, to add drop table if exist commands before each create table, but I need to know the table name to do this, so if the dump file contains something like:

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

...
CREATE TABLE `orders`
...

I need to run something like:

我需要运行类似的东西:

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

to get the result of:

得到以下结果:

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

I'm using the mod_rewrite syntax in the sedcommand as a logical example of what I'm trying to do.

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

Any suggestions?

有什么建议?

回答by Jonathan Leffler

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

Find a CREATE TABLE statement and capture the table name. Replace it with 'DROP TABLE IF EXISTS' and the table name, plus a semi-colon to terminate the statement, and a copy of what was matched to preserve the CREATE TABLE statement.

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

This is classic sednotation. Since you're using bash, there's a chance you're using GNU sedand will need to add --posixto use that notation, or you'll need to fettle the script to use GNU's non-standard sedregexes. I've also not attempted to insert a newline into the output. You can do that with GNU sedif it is important enough to you.

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

The key points are the parentheses (classically needing to be escaped with a backslash) are the capture mechanism, and backslash-number is the replacement mechanism.

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

回答by Kent

 sed -r "s/CREATE TABLE (\`.*\`)/DROP TABLE IF EXISTS \n &/g" dump.sql

test:

测试

kent$  cat t.txt

CREATE TABLE `orders`
...

CREATE TABLE `foo`
...
...

CREATE TABLE `bar`
...


kent$  sed -r "s/CREATE TABLE (\`.*\`)/DROP TABLE IF EXISTS \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`
...

回答by Bhoom Suktitipat

This is called a "back reference". And sed will start numbering the things between the parenthesis. \(...\)

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

Note the use of backslash as an escape character above.

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

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

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

回答by Neil Guy Lindberg

Here is an answer to the OP's question via title of this thread: As @bhoom-suktitipat states: This is called a "back reference"...

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

SUMMARY: Placeholder variables, or back reference lookup is achieved, on the replace side, by using backslash followed by a digit, starting at 1, like so: \1

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

BACKGROUND: I'm here because I've been taking a bunch of code and revamping it. In the process I want to pre-eslint it to find all the double quotes around JSON keys and strip them. ESLint's Quote Props Rulecan be used, with --fix, to do the exact opposite of what I need todo.

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

MISSION OUTLINE:

使命大纲:

Turn { "foo": "bar" }into { foo: "bar" }, a.k.a. using-placeholders-variables-in-a-sed-command

{ "foo": "bar" }{ foo: "bar" },又名使用-占位符变量-IN-A-SID命令

  1. Find the equivalent of the "foo" (key) in the second matching group: ("{1})(\w+)(":{1}).
  2. Use that matching group as a placeholder to render foo:, instead of "foo":
  3. Write changes to file.
  1. 在第二个匹配组中找到“foo”(键)的等价物:("{1})(\w+)(":{1})
  2. 使用该匹配组作为占位符来呈现foo:,而不是"foo":
  3. 将更改写入文件。

Write to different file:

写入不同的文件:

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

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

Write to same file:

写入同一个文件:

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

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

SED flags used:

使用的 SED 标志:

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

-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)

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