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
Using placeholders/variables in a sed command
提问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命令
- Find the equivalent of the "foo" (key) in the second matching group:
("{1})(\w+)(":{1}). - Use that matching group as a placeholder to render
foo:, instead of"foo": - Write changes to file.
- 在第二个匹配组中找到“foo”(键)的等价物:
("{1})(\w+)(":{1})。 - 使用该匹配组作为占位符来呈现
foo:,而不是"foo": - 将更改写入文件。
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)

