我有 pandoc 转换为 HTML 的输出,如下所示:
foo
bar
<blockquote>
That's one small step for man, one giant leap for mankind
A new line and another quote
</blockquote>
baz
我想把它做成这样:
foo
bar<blockquote>That's one small step for man, one giant leap for mankind
A new line and another quote</blockquote>baz
(因为无论如何块引号都是单独渲染的,所以我不需要额外的新行。)
我开始尝试使用 sed,最终得到了这个 awk:
'/./ {printf "%s%s", $0, ($1 ~ /^$/ && $2 ~ /<\/?blockquote>/) ? OFS : ORS}'
它实现了我想要的部分功能,但对我来说有点太高级了,无法理解如何修改。
换句话说,我认为我想要的规则是:如果下一行是空白且后面的一行 matches /<\/?blockquote>/
,则打印当前行、下一行以及后面的一行,不带任何分隔符,然后继续。
答案1
使用 GNU awk 处理多字符RS
、RT
、gensub()
和 ,\s
并且无需将整个文件一次性读入内存:
$ awk -v RS='\\s*</?blockquote>\\s*' '{ORS=gensub(/\s+/,"","g",RT)} 1' file
foo
bar<blockquote>That's one small step for man, one giant leap for mankind
A new line and another quote</blockquote>baz
答案2
使用 aPerl
的单行:
>= 5.36
:
$ perl -gpe 's/(\w+)\n\n(</?blockquote\b[^\n]+)\s*\n/$1$2/g' file
或者< 5.36
:
$ perl -0777 -pe 's/(\w+)\n\n(</?blockquote\b[^\n]+)\s*\n/$1$2/g' file
foo<blockquote>That's one small step for man, one giant leap for mankind
A new line and another quote</blockquote>bar
-g
或-0777
读取内存中的整个文件's///'
是替换骨架,就像sed
$1$2
是两个被捕获的组,\1\2
就像sed
正则表达式匹配如下:
节点 | 解释 |
---|---|
( |
分组并捕获到 $1: |
\w+ |
单词字符(az、AZ、0-9、_)(1 次或多次(匹配尽可能多的数量)) |
) |
1 美元结束 |
\n |
'\n'(换行符) |
\n |
'\n'(换行符) |
( |
分组并捕获到 $2: |
</?blockquote |
'<' + 可选的 '/' + '块引用' |
\b |
词边界锚 |
[^\n]+ |
任何字符,除了: '\n'(换行符)(1 次或多次(匹配尽可能多的数量)) |
) |
2 美元结束 |
\s* |
空格(\n、\r、\t、\f 和 " ")(0 次或多次(匹配尽可能多的数量)) |
\n |
'\n'(换行符) |
答案3
awk 'BEGIN { waiting_for_tag=1; };
NF==0 { next; };
$1 ~ "</?blockquote>" { printf "%s",$1; waiting_for_tag=0; next; };
waiting_for_tag==1 { printf "%s",$0; next; };
{ printf "%s\n",$0; waiting_for_tag=1; }' input
foo<blockquote>That's one small step for man, one giant leap for mankind
A new line and another quote</blockquote>bar