缩进 Fortran 源代码,将缩进传播到未缩进的特殊行

缩进 Fortran 源代码,将缩进传播到未缩进的特殊行

我正在尝试编写自己的脚本来改进一些自动格式化,然后再提交到远程存储库。我在 IDE 中使用缩进指南,并且适用于我的语言 (FORTRAN) 的自动格式化程序不支持缩进空行。我本质上想用来sed遍历文件的行,如果该行为空,则向该行添加空格,直到它与该行具有相同数量的空格它上面(因此忽略第一行)。因为我想将其用作预提交挂钩的一部分,所以如果文件通过了要求并且没有被修改,那就太棒了。

未格式化文件的示例,其中>对应于空格:

Start of document - First line is ignored
Second line has text and is therefore ignored
>>>>Third line has four spaces so below (empty line) should have 4 spaces added.

>>>>>>>>Third line has 8 spaces so below (empty line) should have 8 spaces added.

End of document

期望的输出:

Start of document - First line is ignored
Second line has text and is therefore ignored
>>>>Third line has four spaces so below (empty line) should have 4 spaces added.
>>>>
>>>>>>>>Third line has 8 spaces so below (empty line) should have 8 spaces added.
>>>>>>>>
End of document

另外,与此相关的是我想缩进以感叹号开头的行在第 1 栏(前面没有任何空格)到上面一行的级别(因为我使用的自动格式化程序不支持这一点)。

未格式化文件的示例,其中>对应于空格:

Start of document - First line is ignored
! Second line starts with exclamation mark in column 1 so it is indented to level of above line
>>>>Third line has 4 spaces to start
!This should have 4 spaces added to it because the first character is ‘!’ and above line has 4
>>>>>>>>This line has 8 spaces
>>>>>>>>!This line shouldn’t be changed as it begins with a space, not an exclamation mark.
End of document

期望的输出:

Start of document - First line is ignored
! Second line starts with exclamation mark in column 1 so it is indented to level of above line
>>>>Third line has 4 spaces to start
>>>>!This should have 4 spaces added to it because the first character is ‘!’ and above line has 4
>>>>>>>>This line has 8 spaces
>>>>>>>>!This line shouldn’t be changed as it begins with a space, not an exclamation mark.
End of document

我对 bash 脚本非常陌生,因此任何解决方案如何工作的解释都会很棒,并提前感谢您的帮助!

编辑:按照评论的要求用文本替换图像!

答案1

使用sed

sed -n \
    -e '/^!/ { G; s/\(.*\)\n\(.*\)/\2\1/; }' \
    -e '/^$/g' \
    -e p \
    -e 's/^\( *\).*/\1/' \
    -e h file

这使用一系列sed编辑表达式来执行所需的缩进。该脚本使用保留空间( 中的辅助不可编辑缓冲区sed)将当前缩进保存为多个空格字符。

!如果该行的第一个位置以 a 开头,则触发第一个表达式。该表达式将保留空间中的任何内容附加到当前行末尾,并以换行符作为分隔符,然后交换缓冲区的两部分,同时删除换行符。这会将!-line 缩进到当前的缩进级别。

第二个表达式针对空行而触发,并用保留空间中的任何内容替换空行。这负责向空行添加适当数量的空格。

第三个表达式输出编辑缓冲区的当前内容。我们明确地执行此操作,因为它当前已正确缩进(由于是 -line !、空行,或者是我们尚未修改的其他行),并且我们很快需要修改它以便能够处理文档的其余部分正确。

最后两个操作在空格缩进结束处截断当前行,然后将剩余的缩进保存到保留空间以供下一次循环使用。将最后一个替换中的空格替换为例如,[[:blank:]]以匹配使用制表符或空格进行的任何缩进。

答案2

像这样的任务最好用awkor之类的语言来完成perl(因为 sed 没有变量)。

以下 Perl 一行代码适用于您的两种要求。我已将输出通过管道传输到,cat -A以便您可以看到空格已添加到需要的行的开头 -$表示每行的结尾。

第一个语句将变量的内容添加$spaces到行 ( $_) 的开头,如果它为空或!在第一个输入行上以 - 开头,$spaces则将为空。第二条语句将当前行开头的空格(如果有)捕获到 中$spaces,准备在下一个输入行中使用。

注意:这里使用\h,表示水平空白(ASCII 文件中的空格和制表符,以及一些 unicode 空格字符)。如果您希望它仅使用空格字符,请将 更改\h为单个空格:($spaces) = (/^( *)/)

第一个输入文件:

$ perl -p -e 'if (/^($|!)/) { $_ = $spaces . $_ };
              ($spaces) = (/^(\h*)/)' input1.txt  | cat -A
Start of document - First line is ignored$
Second line has text and is therefore ignored$
    Third line has four spaces so below (empty line) should have 4 spaces added.$
    $
        Third line has 8 spaces so below (empty line) should have 8 spaces added.$
        $
End of document$

第二个文件:

$ perl -p -e 'if (/^($|!)/) { $_ = $spaces . $_ };
              ($spaces) = (/^(\h*)/)' input2.txt  | cat -A
Start of document - First line is ignored$
! Second line starts with exclamation mark in column 1 so it is indented to level of above line$
    Third line has 4 spaces to start$
    !This should have 4 spaces added to it because the first character is '!' and above line has 4$
        This line has 8 spaces$
        !This line shouldn't be changed as it begins with a space, not an exclamation mark.$
End of document$

另请注意:这会将文件(无论是否修改)打印到标准输出。如果您希望它修改原始文件,请将 perl 的-i选项添加到命令行 - 这与sed-i选项类似。请参阅man perlrun并搜索-i\[extension\]详细信息) - 特别要注意以下几点:

请注意,由于-i在创建同名新文件之前重命名或删除了原始文件,因此不会保留 Unix 风格的软链接和硬链接。

git似乎并不关心文件的索引节点号是否发生变化,仅当内容发生变化时...但是如果您需要保留硬链接或者只是不想覆盖输入文件(如果它尚未更改),那么重定向到临时文件,并且仅当diffcmp指示临时文件不同时才覆盖。

相关内容