![如何编写脚本以根据括号嵌套的深度来缩进输入文件中的行?](https://linux22.com/image/153228/%E5%A6%82%E4%BD%95%E7%BC%96%E5%86%99%E8%84%9A%E6%9C%AC%E4%BB%A5%E6%A0%B9%E6%8D%AE%E6%8B%AC%E5%8F%B7%E5%B5%8C%E5%A5%97%E7%9A%84%E6%B7%B1%E5%BA%A6%E6%9D%A5%E7%BC%A9%E8%BF%9B%E8%BE%93%E5%85%A5%E6%96%87%E4%BB%B6%E4%B8%AD%E7%9A%84%E8%A1%8C%EF%BC%9F%20.png)
脚本的参数是缩进字符 c 和每层的字符数 n,这些参数后跟文件列表(如果未提供文件,则使用标准输入)。然后,该脚本逐行读取,并在每一行中删除行首的白色字符,并将其替换为 k*n 个字符 c,其中 k 是括号嵌套的级别。考虑普通括号 ()、大括号 {} 和方括号 []。例如输入文件
a ( b
c d [ e ] f [
g h { j (
k ) } l m
n ] o ) p
q r
would be modified as follows if the script is run with parameters c='.' and n=1:
a ( b
.c d [ e ] f [
..g h { j (
....k ) } l m
..n ] o ) p
q r
(假设输入有配对良好的括号。必须允许使用空格或制表符作为字符 c)
答案1
“如何编写脚本”:将问题分解为更容易转化为代码的更小的步骤:
- 一次一行读取你的文件
- 计算左/右括号的数量,并相应地更新运行总计
- 这可以通过一次一个字符地处理该行或通过其他方式来完成
- 创建一个
c
长度为“运行总数”的字符串 - 打印该字符串和该行。
- 考虑边缘情况和错误条件:考虑到你问题中的假设,我想这将是额外的学分:
- 如果运行总计变为负值会发生什么情况
- 如果文件末尾的运行总计大于零会发生什么
答案2
这是我提出的解决方案。我以你的例子作为输入。这个想法是:
- 删除所有现有缩进
- 逐行读取输入
- 在每一行中,计算左括号 :
(
and[
和的数量{
,并相应地增加“缩进级别” - 对于同一行,计算右括号并减少“缩进级别”
- 替换变量,因为左括号会导致以下行缩进
- 生成“缩进字符串”,即“缩进字符”重复“缩进级别”次
- 输出“缩进字符串”+每行内容
- 重复直到输入结束
#!/usr/bin/env bash
fileToReindent='./testFile'
indentCharacter='.'
countOccurrencesOfNeedleInHaystack() {
local needle=$1
local haystack=$2
echo "$haystack" | grep -o "$needle" | wc -l
}
makeIndentString() {
local indentCharacter=$1
local indentLevel=$2
python -c "print('$indentCharacter' * $indentLevel)"
}
# delete all existing indents
sed -ri 's/^ (.)$/\1/' "$fileToReindent"
# indent lines
indentLevelOfCurrentLine=0
indentLevelOfNextLine=0
while read line; do
for character in '(' '[' '{'; do
nb=$(countOccurrencesOfNeedleInHaystack "$character" "$line")
indentLevelOfNextLine=$((indentLevelOfNextLine+nb))
done
for character in ')' ']' '}'; do
nb=$(countOccurrencesOfNeedleInHaystack "$character" "$line")
indentLevelOfNextLine=$((indentLevelOfNextLine-nb))
done
indentString=$(makeIndentString "$indentCharacter" "$indentLevelOfCurrentLine")
indentLevelOfCurrentLine=$indentLevelOfNextLine
echo "$indentString$line"
done < "$fileToReindent"
注意:此代码只是概念证明,仍需要完善。
NB2:在渲染的代码块中存在额外空白行的问题。欢迎编辑;-)