Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/blackberry/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash 使用“sed”将代码块中的文本替换为代码块顶部的命令输出_Bash_Awk_Sed - Fatal编程技术网

Bash 使用“sed”将代码块中的文本替换为代码块顶部的命令输出

Bash 使用“sed”将代码块中的文本替换为代码块顶部的命令输出,bash,awk,sed,Bash,Awk,Sed,我有一个标记文件,其中包含类似以下示例的代码片段: ``` $ cat docs/code_sample.sh #!/usr/bin/env bash echo "Hello, world" ``` 这意味着在docs/code\u sample.sh位置有一个文件,其内容是: #!/usr/bin/env bash echo "Hello, world" 我想用sed(awk或perl也可以)解析标记文件,并用上面的bash命令计算的结果替换代码段的底部,例如cat docs/code\

我有一个标记文件,其中包含类似以下示例的代码片段:

```
$ cat docs/code_sample.sh

#!/usr/bin/env bash
echo "Hello, world"
```
这意味着在
docs/code\u sample.sh
位置有一个文件,其内容是:

#!/usr/bin/env bash
echo "Hello, world"

我想用
sed
awk
perl
也可以)解析标记文件,并用上面的bash命令计算的结果替换代码段的底部,例如
cat docs/code\u sample.sh
计算的结果。

perl救命

perl -0777 -pe 's/(?<=```\n)^(\$ (.*)\n\n)(?^s:.*?)(?=```)/"$1".qx($2)/meg' < input > output

perl-0777-pe的/(?perl拯救一切

perl -0777 -pe 's/(?<=```\n)^(\$ (.*)\n\n)(?^s:.*?)(?=```)/"$1".qx($2)/meg' < input > output

perl-0777-pe的/(?如果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


祝您好运。

如果您的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


祝你好运。

使用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
$cat tst.awk
状态==“正在导入”{
而((getline<$NF)>0){
打印行
}
收盘价($NF)
state=“已导入”
}
$0==“``{state=(state?”:“importing”)}
状态!=“已导入”{print}
$awk-f tst.awk文件

有关getline的用法和注意事项,请参阅。

使用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
$cat tst.awk
状态==“正在导入”{
而((getline<$NF)>0){
打印行
}
收盘价($NF)
state=“已导入”
}
$0==“``{state=(state?”:“importing”)}
状态!=“已导入”{print}
$awk-f tst.awk文件

有关getline的用法和注意事项,请参阅。

因此,始终会有一个3个反勾号的行,后面跟着一个命令,例如带前导的
$
的cat docs/code\u sample.sh
,然后是一个空行?您想用第一个命令行的输出替换从第一个空行到最后3个反勾号的所有内容,是吗?@paulhodge是的,这完全正确。因此,始终会有一个3个反勾号行,后面跟着一个命令,例如
cat docs/code\u sample.sh
和一个前导的
$
,然后是一个空行?您想用第一个命令行的输出替换从第一个空行到最后3个反勾号的所有内容,是吗?@PaulHodges,没错没错。有了所有这些不直观的选项,Perl脚本经常被戏称为“只写”也就不足为奇了@DodgyCodeException:只有三个选项,其中两个相当标准。在生产代码中,我不会使用一行,可能会使用
/x
@choroba注释正则表达式。这几乎对我有效,尽管无论何时
输入
=
输出
,例如
file.md
file.md
wi我将以空结束。如何避免这种情况?输出到另一个文件,然后重命名它。有了所有这些不直观的选项,Perl脚本通常被戏称为“只写”也就不足为奇了@DodgyCodeException:只有三个选项,其中两个相当标准。在生产代码中,我不会使用一行,可能会使用
/x
@choroba注释正则表达式。这几乎对我有效,尽管无论何时
输入
=
输出
,例如
file.md
file.md
wi将以空结尾。如何避免此问题?输出到另一个文件,然后重命名。请注意,它不会进行就地编辑。这会将源文件的备用版本输出到标准输出,以便您重定向到临时文件,在执行其他操作之前,您可以在该临时文件中进行查看。接受解决方案吗?此外,请查看更多有用的详细信息如何实际使用循环,对于一些复杂的示例,尽管它们不太适合这种情况。特别是,本节可能会有所帮助。请注意,它不会进行就地编辑。这将把源文件的备用版本输出到stdout,以便您重定向到临时文件中,在执行任何操作之前,您可以在其中查看它e、 接受解决方案?此外,请查看更多关于如何实际使用循环的有用见解,以及一些复杂的示例,尽管它们不太适合这种情况。特别是,本节可能会有所帮助。