我有一个markdown文件,其中包含类似于以下示例的代码片段:
```
$ cat docs/code_sample.sh
#!/usr/bin/env bash
echo "Hello, world"
```
这意味着在docs/code_sample.sh
位置有一个文件,其内容为:
#!/usr/bin/env bash
echo "Hello, world"
我想用sed
来解析markdown文件(awk
或perl
也可以)并将代码段的底部替换为上述bash命令求值的内容,例如cat docs/code_sample.sh
计算得出的结果。
答案 0 :(得分:3)
抢救Perl!
perl -0777 -pe 's/(?<=```\n)^(\$ (.*)\n\n)(?^s:.*?)(?=```)/"$1".qx($2)/meg' < input > output
-0777
将整个文件插入到内存中-p
在处理后打印输入s/PATTERN/REPLACEMENT/
与sed
中的替换类似/g
在全球范围内替换,即可以替换的次数/m
使^
匹配每行的开头,而不是整个输入字符串的开头/e
将替换项评估为代码(?<=```\n)
的意思是“在三个反引号和一个换行符之前” (?^s:.*?)
也会更改.
的行为以匹配换行符,因此它(由于*?
而节俭地)匹配了其余的预格式化块(?=```)
的意思是“后跟三个反引号” qx
在shell中运行参数并返回其输出答案 1 :(得分:1)
如果您的GNU版本带有e
命令,那么仅sed解决方案会更容易。
也就是说,这是一个快速,简单且有点笨拙的版本,我打掉了这个版本,不必费心检查上一行或下一行的值-只是假设您的格式是好的,并且没有任何循环或任何其他东西其他。不过,对于我的示例代码,它仍然有效。
我首先制作了a
,b
和x
这两个标记文件。
$: cat a
#! /bin/bash
echo "Hello, World!"
$: cat b
#! /bin/bash
echo "SCREW YOU!!!!"
$: cat x
```
$ cat a
foo
bar
" b a z ! "
```
```
$ cat b
foo
bar
" b a z ! "
```
然后我写了s
脚本sed
。
$: cat s
#! /bin/env bash
sed -En '
/^```$/,/^```$/ {
# for the lines starting with the $ prompt
/^[$] / {
# save the command to the hold space
x
# write the ``` header to the pattern space
s/.*/```/
# print the fabricated header
p
# swap the command back in
x
# the next line should be blank - add it to the current pattern space
N
# first print the line of code as-is with the (assumed) following blank line
p
# scrub the $ (prompt) off the command
s/^[$] //
# execute the command - store the output into the pattern space
e
# print the output
p
# put the markdown footer back
s/.*/```/
# and print that
p
}
# for the (to be discarded) existing lines of "content"
/^[^`$]/d
}
' $*
它可以完成工作,并且可能会让您入门。
$: s x
```
$ cat a
#! /bin/bash
echo "Hello, World!"
```
```
$ cat b
#! /bin/bash
echo "SCREW YOU!!!!"
```
很多警告-最好检查$
后面是否有一行反引号,然后是一个空行,也许要确保文件中没有虚假的东西可以被执行...但是这样做(GNU)sed
向您询问的内容。
祝你好运。
答案 2 :(得分:1)
使用getline的一种罕见情况是合适的:
$ cat tst.awk
state == "importing" {
while ( (getline line < $NF) > 0 ) {
print line
}
close($NF)
state = "imported"
}
$0 == "```" { state = (state ? "" : "importing") }
state != "imported" { print }
$ awk -f tst.awk file
有关获取热线的用途和注意事项,请参见http://awk.freeshell.org/AllAboutGetline。