リモートリポジトリにコミットする前に、一部の自動書式を改善するために独自のスクリプトを作成しようとしています。私の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で始まる場合、最初の式がトリガーされます。この式は、改行文字を区切り文字として使用して、予約済みスペースの内容を現在の行の末尾に追加し、バッファの2つの部分を交換して改行文字を削除します。!
現在のインデントレベルに-lineをインデントします。
2番目の式は空の行に対して実行され、予約済みスペースの内容に置き換えられます。空白行に適切な量のスペースを追加するのに役立ちます。
3番目の式は、編集バッファの現在の内容を出力します。現在正しくインデントされているので(-line !
、空の行、またはまだ変更していない他の行のため)、これを明示的に実行し、残りの部分を処理できるようにすぐに修正する必要があります。文書を正しく。
最後の2つの操作は、スペースのインデントの末尾で現在の行を切り取り、ループを介して次回に使用できるように、残りのインデントをスケジュールされたスペースに保存します。たとえば、[[:blank:]]
タブまたはスペースを使用してインデントと一致するように、最後の置換のスペースを置き換えます。
答え2
このような操作は、awk
または同じ言語で最もよく行われますperl
(sedには変数がないため)。
次の1行のPerlコードは、両方の要件に適しています。必要な行の先頭にスペースが追加され、各行の終わりを示すことがわかるようにcat -A
出力をパイプに接続しました。$
最初のステートメントは、変数の内容を$spaces
行の先頭( )に追加します。$_
行が空の場合、または!
最初の入力行で-で始まる場合は$spaces
空になります。 2番目のステートメントは、現在行(存在する場合)の先頭にあるスペースをキャプチャして、$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$
2番目のファイル:
$ 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$
また、注:これはファイル(修正されているかどうかにかかわらず)を標準出力として印刷します。ソースファイルを変更するには、-i
コマンドラインにperlオプションを追加します。これはsed
perl-i
オプションと似ています。詳細については確認man perlrun
と検索-i\[extension\]
) - 次の点に特に注意してください。
-i
同じ名前の新しいファイルを作成する前に元のファイルの名前が変更または削除されるため、Unixスタイルのソフトリンクとハードリンクは保持されません。
git
ファイルの inode 番号が変更されても内容が変更された場合のみ気にしないようです。ただし、ハードリンクを維持する必要がある場合、または入力ファイルがまだ変更されていない場合、上書きしたくない場合はリダイレクトしてください。一時ファイルに保存し、一時ファイルが異なる場合diff
にのみ上書きします。cmp