次のスクリプトは、期待どおりの Markdown 出力を生成するはずです。
eval "set -n; $x"
コマンドの構文エラーをチェックして、コマンドが完全かどうかを確認するために使用されます。構文エラーのないコマンドのみが完了したと見なされ、実行され、出力 Markdown に表示されます。
処理される入力スクリプトはサブシェルで実行されるため、処理スクリプト自体に干渉しないことに注意してください (つまり、入力スクリプトは処理スクリプトと同じ変数名を使用でき、変数の値を変更することはできません)。処理スクリプト内)。唯一の例外は、 と呼ばれる特殊変数です___internal__variable___
。
それを達成する方法には2 つのアプローチがありますが、それを以下に示します。バージョン 1では、新しい完全なコマンドが処理されるたびに、それより前のすべてのステートメントが実行され、コマンドの「コンテキスト」が作成されます。これにより、入力スクリプトが効果的に複数回実行されます。
バージョン 2では、完全なコマンドが実行されるたびに、サブシェルの環境が変数に格納されます。その後、次のコマンドが実行される前に、以前の環境がサブシェルで復元されます。
バージョン 1
#!/bin/bash
x="" # Current
y="" # Context
while IFS= read -r line # Keep indentation
do
[ -z "$line" ] && continue # Skip empty lines
x=$x$'\n'$line # Build a complete command
# Check current command for syntax errors
if (eval "set -n; $x" 2> /dev/null)
then
# Run the input script up to the current command
# Run context first and ignore the output
___internal_variable___="$x"
out=$(eval "$y" &>/dev/null; eval "$___internal_variable___")
# Generate command markdown
echo "=================="
echo
echo "\`\`\`bash$x"
echo "\`\`\`"
echo
# Generate output markdown
if [ -n "$out" ]
then
echo "Output:"
echo
echo "\`\`\`"
echo "$out"
echo "\`\`\`"
echo
fi
y=$y$'\n'$line # Build context
x="" # Clear command
fi
done < input.sh
バージョン 2
#!/bin/bash
x="" # Current command
y="true" # Saved environment
while IFS= read -r line # Keep indentation
do
[ -z "$line" ] && continue # Skip empty lines
x=$x$'\n'$line # Build a complete command
# Check current command for syntax errors
if (eval "set -n; $x" 2> /dev/null)
then
# Run the current command in the previously saved environment
# Then store the output of the command as well as the new environment
___internal_variable_1___="$x" # The current command
___internal_variable_2___="$y" # Previously saved environment
out=$(bash -c "${___internal_variable_2___}; printf '<<<BEGIN>>>'; ${___internal_variable_1___}; printf '<<<END>>>'; declare -p" 2>&1)
# Separate the environment description from the command output
y="${out#*<<<END>>>}"
out="${out%%<<<END>>>*}"
out="${out#*<<<BEGIN>>>}"
# Generate command markdown
echo "=================="
echo
echo "\`\`\`bash$x"
echo "\`\`\`"
echo
# Generate output markdown
if [ -n "$out" ]
then
echo "Output:"
echo
echo "\`\`\`"
echo "$out"
echo "\`\`\`"
echo
fi
x="" # Clear command
fi
done < input.sh
例
入力スクリプトの場合input.sh
:
x=10
echo "$x"
y=$(($x+1))
echo "$y"
while [ "$y" -gt "0" ]
do
echo $y
y=$(($y-1))
done
出力は次のようになります。
==================
```bash
x=10
```
==================
```bash
echo "$x"
```
Output:
```
10
```
==================
```bash
y=$(($x+1))
```
==================
```bash
echo "$y"
```
Output:
```
11
```
==================
```bash
while [ "$y" -gt "0" ]
do
echo $y
y=$(($y-1))
done
```
Output:
```
11
10
9
8
7
6
5
4
3
2
1
```