我正在尝试弄清楚如何复制文本文件中的单个行范围。该范围以文件中唯一的行开始,但以可存在于文件中多个位置的行结束。
这是我需要处理的一些示例输入:
我没有想象力 所以这个示例文本将 常见的 很无聊。但确实如此 展示问题 我正在努力解决。 常见的 嗨妈妈! 这是一条独特的线路。 还有更多 应复制的文本 以及。 常见的 后面应该是文字 不被复制。
我需要复制和修改的行以粗体显示,以在此处指出。
我需要的输出是:
我没有想象力 所以这个示例文本将 常见的 很无聊。但确实如此 展示问题 我正在努力解决。 常见的 嗨妈妈! 这是一条改变的线。 而这里更不一样 应复制的文本 以及。 常见的 这是一条独特的线路。 还有更多 应复制的文本 以及。 常见的 后面应该是文字 不被复制。
附加输出以粗体显示以使其清晰。
我需要获取以行开头的行范围:
这是一条独特的线路
并以以下行结尾:
常见的
该范围的行必须插入到原始范围的行之前。匹配行范围的副本需要稍微修改。
结束范围的“公共”行本身可以出现在文件内的许多位置。
我想出了一个工作awk
脚本,但它似乎比需要的要复杂得多。我的awk
技能根本不存在。
/This is a unique line/{flag=1}
/Common/{
if (flag > 0) {
n=m;
sub("some","different",n);
sub("unique","changed",n);
print n "\n" $0 "\n" m;
m=""
};
flag=0
};
flag{
if (length(m) > 0) {
m=m "\n" $0
} else {
m=$0
}
}
!flag{ print }
有没有更干净、更简洁的方法来实现这个?除此之外,我对其他选择持开放态度awk
。它只需是 macOS 上可用的标准命令即可。
答案1
使用ex
, POSIX 指定的文件编辑器(以及 的非视觉形式vi
)。
printf '%s\n' '/This is a unique line' '.,/Common/copy -' %p | ex file.txt
这会打印修改后的文件内容,但不保存更改。
这是保存更改的命令:
printf '%s\n' '/This is a unique line' '.,/Common/copy -' x | ex file.txt
与 Awk 和 Sed 不同,ex
它不仅限于按顺序修改行。相反,它可以对整个缓冲区进行操作,而不仅仅是向前移动。
第一个命令/This is a unique line
只是一个运动命令。它将光标移动到具有This is a unique line
.
下一个命令是copy
命令。它对从当前行 ( .
) 到匹配的下一行的地址范围进行操作Common
,并将它们复制到当前行 ( -
) 之前的行。
更新:为了复制后修改,我们首先标记我们开始的行。要复制的第一行将标记为“b”,其之前的行将标记为“a”。然后复制的行将放在 'a 和 'b 之间,我们可以在地址中使用这些行作为我们的“替换”命令。顺便说一下,Andt
是 的同义词。copy
printf "/Here is a unique line
kb
-ka
.,/Common/t 'a
'a+,'b-s/unique/changed/g
'a+,'b-s/some/different/g
x
" | ex file.txt
答案2
sed -e '
/This is a unique line/,/Common/!b
H
/Common/!d
g
s/^\n//
h
s/unique/changed/
s/some/different/
G
' yourfile
解释
- 我们首先拒绝任何非范围的行。
- 对于范围内的每一行,我们将其附加到保留空间。
- 我们删除所有读入的行,直到看到公共行。此时,我们检索保留区域(应该具有整个范围+前导“\n”)。
- 我们删除这个前导换行符并更新保留。这是由于
H
命令 BTW 造成的。 - 现在我们进行编辑:独特 -> 更改,一些 -> 不同,...
- 将保留空间(未更改的版本)附加到模式空间(更改的版本)。
- sed 将自动打印模式空间中的内容。
答案3
awk '/This is a unique line/,/Common/{
H = H RS $0
if ( $0 ~ /Common/ ) {
g = H
sub("\n","",g)
sub("some","different",g)
sub("unique","changed",g)
$0 = g H
} else { next }
}1' inputfile
这是sed
翻译为awk
.
请注意,您拥有的代码负责打开/关闭awk
变量标志以跟踪行。但是,当您使用它的运算符awk
时,已经在幕后为您做了完全相同的事情range
,