最後の構成行の後にテキストを挿入するにはどうすればよいですか?

最後の構成行の後にテキストを挿入するにはどうすればよいですか?

構成ファイルに自動的に1行を挿入する必要がありますが、挿入する必要があるという警告が表示されます。今後複数行フッターコメントと以前の空白または空白のみの行フッターが存在する場合。それは、最後の構成行の後に新しい行を挿入する必要があります。、元のファイルと1行の比較を行います。擬似コードで:

  1. ファイルの末尾に移動します。
  2. ファイルの最初の(最後の)構成行(つまり、空ではない行、空白のみの行、コメントのみの行、またはコメントの後にスペースがある行)に戻ります。
  3. 現在の行の後にテキストを挿入します。

構成行の拡張正規表現:^\s*[^[:space:]#]

一般的な*nixツール(例えば、、、、sedまたはawkedex機能するはずです。


考えられる解決策と問題:

  • 使用tacダブルクリックすると、リバース検索の問題ではなく、フォワード検索の問題になります。これは、単一のコマンドでこれを実行するのではなく、結果を一時ファイルに保存してから元のファイルを置き換える必要があることを意味します。
  • sed -iそして使用裏返すいたずら。これは、ファイル全体をメモリに保存することを意味します。
  • ex -c '1' -c '?^\s*[^[:space:]#]?' -c $'a\nmy new line\n.' -c 'wq' /path、完全なファイルがメモリに保存されることも学びました。

2つの問題を同時に解決できるソリューションはありませんか?

スタートアップファイルの例:

# Universe configuration
#

pi = 3 # A good #
e = mc**2 # To within a hair

[cut 200 trillion lines]

# 
# END
#

入力例:

sol { mass = 42, start = 9.2 }

予想出力:

# Universe configuration
#

pi = 3 # A good #
e = mc**2 # To within a hair

[cut 200 trillion lines]
sol { mass = 42, start = 9.2 }

# 
# END
#

共通機能に基づいて@StephaneChazelasのソリューション

答え1

次の操作を実行できます。

file=/some/file
newtext='sol { mass = 42, start = 9.2 }'
tac -- "$file" | 
  NEWTEXT=$newtext awk -v size="$(wc -c < "$file")" '
    $1 ~ /^[^#]/ {
      system("dd bs=1 seek=" size - length(footer) " conv=notrunc if=/dev/null")
      printf "%s\n%s", ENVIRON["NEWTEXT"], footer
      exit
    }
    {footer=$0 "\n" footer}' 1<> "$file"

これによりファイルが上書きされ、フッターのみがメモリに保存されます。非標準のGNUtacコマンドが必要です。ファイルはプレーンテキストファイルでなければなりません。

答え2

awk唯一の解決策(gawkでテスト):

$ awk '
    BEGIN   {   footer = ""; wl = ""; } 
    END     {   while(( getline line < "sol.txt") > 0 ) {
                    print(line)
                }
                footer = wl footer
                print substr(footer, 0, length(footer)-1); 
            }

    # Blank line
    /^[[:blank:]]*$/ {
                if (footer) {
                    footer = wl footer
                    print substr(footer, 0, length(footer)-1); 
                    footer = ""
                }
                wl = $0 "\n"
            }
    # Comment only
    /^[[:blank:]]*#/ {
                footer = footer $0 "\n"; 
            }

    # Configuration line
    /^[[:blank:]]*[^[:space:]#]/ {
                print(wl footer $0); wl = ""; footer = ""; 
            }
    ' <  universe.txt > universe2.txt

生産:

# Universe configuration
#

pi = 3 # A good #
e = mc**2 # To within a hair

[cut 200 trillion lines]
sol { mass = 42, start = 9.2 }

# 
# END
# 

1行の違い:

sh$ diff universe*.txt
8d7
< sol { mass = 42, start = 9.2 }

答え3

これは設定ファイルなので、メモリに適しています。ストリームとして処理する必要はありません。

newline='
' tab=$(echo | tr '\n' '\t')
old=$(cat foo.config)
footer=${old##*"$newline[!$newline$tab #]"}
if [ "$footer" = "$old" ]; then
  footer=
else
  footer=${footer#*"$newline"}
fi
head=${old%"$footer"}
echo "$head$text_to_insert$footer" >foo.config.new

関連情報