tur*_*tle 8 sed awk text-processing
我正在尝试使用 sed 获取文件的内容并将其插入到另一个文件中的匹配模式之后。我的问题与此问题非常相似,但我希望插入文件的内联内容而不是新行。我怎样才能做到这一点?
使用我引用的示例问题,第一个答案正是我想要的;但是,我希望插入发生内联:
sed '/First/r file1.txt' infile.txt
Run Code Online (Sandbox Code Playgroud)
我要插入的实际数据是一个 JSON 文件:
[
{
"foo": "bar",
"baz": "biff",
"data": [
{
"a": 1945619,
"b": [
{
"c": 512665,
"d": "futz"
}
]
}
]
}
]
Run Code Online (Sandbox Code Playgroud)
在您链接的问题中已经有很好的awk
答案,只需通过使用printf
而不是print
插入不带换行符的内容稍微修改一下:
awk '/First/ { printf $0; getline < "File1.txt" }1' infile.txt
Run Code Online (Sandbox Code Playgroud)
结果:
Some Text here
FirstThis is text to be inserted into the File.
Second
Some Text here
Run Code Online (Sandbox Code Playgroud)
您可能希望在“First”之后添加空格或其他分隔符 printf $0 " "; ...
如果插入的文件有很多行,那么:
awk '/First/{printf $0; while(getline line<"File1.txt"){print line};next}1' infile.txt
Run Code Online (Sandbox Code Playgroud)
结果:
Some Text here
First[
{
"foo": "bar",
"baz": "biff",
"data": [
{
"a": 1945619,
"b": [
{
"c": 512665,
"d": "futz"
}
]
}
]
}
]
Second
Some Text here
Run Code Online (Sandbox Code Playgroud)
您可以使用perl
(获取文件内容并替换pattern
为pattern
+ file content
):
perl -pe '$text=`cat insert.txt`; chomp($text); s/PAT/$&$text/' file.txt
Run Code Online (Sandbox Code Playgroud)
添加-i
到位编辑;g
在每个 PAT(模式)出现后追加,例如:
perl -i -pe '$text=`cat insert.txt`; chomp($text); s/PAT/$&$text/g' file.txt
Run Code Online (Sandbox Code Playgroud)
另一种方式,使用ed
:
printf '%s\n' /PAT/s/PAT/\&\\ \/ - kb ". r insert.txt" j \'b j ,p q | ed -s file.txt
Run Code Online (Sandbox Code Playgroud)
就地编辑,替换,p
为w
:
printf '%s\n' /PAT/s/PAT/\&\\ \/ - kb ". r insert.txt" j \'b j w q | ed -s file.txt
Run Code Online (Sandbox Code Playgroud)
可能没有人对它的工作原理感兴趣,但无论如何,printf
将命令列表传递给ed
:
perl -pe '$text=`cat insert.txt`; chomp($text); s/PAT/$&$text/' file.txt
Run Code Online (Sandbox Code Playgroud)
或者,不使用printf
and |
:
ed -s file.txt <<< $'/PAT/s/PAT/&\\\n/\n-\nkb\n. r insert.txt\nj\n\'b\nj\nw\nq\n'
Run Code Online (Sandbox Code Playgroud)
因此,使这项工作可移植会有点棘手sed
- 您应该寻找cut
和/或paste
使用一些正则表达式前体在该上下文中生成他们的脚本 - 这是因为sed
总是会在ead的输出之前插入一个\n
ewline 。尽管如此,使用 GNU :r
sed
sed '/First/{x;s/.*/cat file/e;H;x;s/\n//}' <<\IN
First
Second
Third
IN
Run Code Online (Sandbox Code Playgroud)
该工程由e
xecutingcat
每次遇到你的时间/First/
地址。它在h
旧空间中执行此操作(无论如何 - 一种备用缓冲区 - 因为我x
改变了它们,它实际上发生在曾经是h
旧空间的模式空间中)以保留行匹配的内容,First
然后附加cat
的输出到您的线路并删除中间的\n
ewline。
First[
{
"foo": "bar",
"baz": "biff",
"data": [
{
"a": 1945619,
"b": [
{
"c": 512665,
"d": "futz"
}
]
}
]
}
]
Second
Third
Run Code Online (Sandbox Code Playgroud)
现在,如果你想要的文件的全部内容,以适应之间有工作有点不同线路的两个部分,因为有上面的命令我刚才删除的换行符结束的匹配行和文件的开头。不过,您也可以这样做:
sed '/First/{s//&\n/;h
s/.*/{ cat file; echo .; }/e;G
s/\(.*\).\n\(.*\)\n/\2\1/
}' <<\IN
Third
Second
First Second Third
Third
Second
First Second Third
IN
Run Code Online (Sandbox Code Playgroud)
将匹配处的行与\n
ewline 字符分开,将其保存在h
旧空间中,e
xecutes cat
- 用其输出替换模式空间 -G
在另一个\n
ewline 字符之后将保留空间的内容附加到我们的新模式空间,然后重新排列\n
ewline 分隔符。
我确实echo .
保留了任何尾随的\n
ewline 字符file
- 但如果这不是您的愿望(并且与您的示例无关),您可以不使用它并在以下替换中删除第一个.
之前.\n
的s///
字符。
就在重新排列模式空间之前,如下所示:
^cat's output - any number of newlines.*.\nmatch on First\nrest of match$
Run Code Online (Sandbox Code Playgroud)
Third
Second
First[
{
"foo": "bar",
"baz": "biff",
"data": [
{
"a": 1945619,
"b": [
{
"c": 512665,
"d": "futz"
}
]
}
]
}
] Second Third
Third
Second
First[
{
"foo": "bar",
"baz": "biff",
"data": [
{
"a": 1945619,
"b": [
{
"c": 512665,
"d": "futz"
}
]
}
]
}
] Second Third
Run Code Online (Sandbox Code Playgroud)