我有一个如下所示的文本文件:
(empty)
str
int
int
如果我将其添加s/^/\</g
到我当前的 sed (使其成为's/\&/\</g;s/\</\ /g;s/^/\</g'
),这就是输出。
< ##only this line gets a <
str
int
int
但是如果我新建一行,然后输入整个命令,例如sed -i '' 's/^/\</g' *.p*
,这就是输出
<
<str
<int
<int
这有什么区别呢?
答案1
区别在于输入和输出。在第一种情况下,您插入了\n
换行符,是的,但您仍在相同的模式空间上操作 - 因此^
模式空间的头部仍保留在原处,即使它包含嵌入的换行符 - 每次出现时您都会插入换行符<
。
但在第二种情况下,您正在使用新的sed
并读取最后一个sed
s 输出作为输入 - 因此,所有这些换行符现在都将第一个循环计数作为单独的输入行注入,并且每个换行符都有自己的^
模式空间头。
echo ..... |
sed 's/./&\
/g;s/^/sed1/' |
sed 's/^/sed2/'
sed2sed1.
sed2.
sed2.
sed2.
sed2.
sed2
顺便一提...
sed 's/&/</g;s/</\
/g'
...可能更容易写...
sed 'y/&</\n\n/'
...但是如果你只是想在每个后面添加一个换行符[&<]
并替换每个,&
那么<
你可以这样做:
sed 's/[&<]/<\
/g'
...但是您的输出与您的输入根本不匹配...
答案2
sed 'expression;expression'
是相同的
sed -e 'expression' -e 'expression'
其中,在几个简单的情况下,与
sed -e 'expression' | sed -e 'expression'
就您而言(据我所知),您正在尝试将所有内容更改&
为<
.然后全部<
换行,最后添加<
到行的开头:
s/\&/\</g;s/\</\
/g;s/^/\</g
根据给定的输入,该sed
脚本将使用 BSD 执行以下操作sed
:
$ sed -f script.sed file
<
<
<
<
或者,使用 GNU sed
:
$ gsed -f script.sed file
<
<
str
<
int
<
int
为什么是这样?
- 首先,
&
文件中没有(\
前面的&
可以另外删除),因此第一个表达式是无操作。 - 第二个表达式匹配
\<
单词边界(的开头)。老实说,我对为什么 BSD 删除该文本感到有点困惑sed
(我将看看这是否是 OpenBSD 中的错误sed
)。因此,这会在示例文件的每个单词的开头插入一个换行符。 - 第三个表达式仍然对同一(现已修改)输入行进行操作,并
<
在该行的开头插入 a 。
与此相反,单个表达式s/^/\</g
(其中不需要\
前面的<
和g
修饰符)将仅<
在每行的开头插入 a 。
后续:已确认sed
OpenBSD 6.1-stable 上的实现存在一个错误,涉及在以插入的换行符开头的行前面添加字符串。补丁已提交。