csplitとsedを使用するスクリプトを理解するのに役立ちます。

csplitとsedを使用するスクリプトを理解するのに役立ちます。

Reference Manager Zoteroからノートをエクスポートする簡単な方法が必要です。複数のメモを選択し、空のテキストファイルにドラッグすることから始めます。また、メモの「原子性」を達成したいので、個々のメモを含む結果のテキストファイルを破線で区切られたセクションに分割する必要があります。次に、各コメントに付与したタイトルを使用して新しいファイルの名前を指定したいと思います。つまり、各セクションの最初の行に名前を変更します。この新しいファイルをマークダウンファイルとして保存したいと思います。

私が書いたスクリプトは、Web上の貢献者が各機能について提案したもので構成されています。私と同様のユースケースを持つ同僚とスクリプトを共有する前に、スクリプトのコマンドを正しく理解していることを確認しようとしています。 「head」コマンドで「$ f」の周りに引用符が必要であることについての私の理解(Gilesの答えを別の質問に読んでください - 以下のリンクを参照)は間違っているようです。引用符なしでスクリプトを試しましたが、同じ結果が得られました。課題の右側に「$f」が表示されるので、二重引用符が必要ないというのは正しいですか?必要ないときに覚えているよりも基本的に二重引用符を使用する方が簡単なので、存在するのでしょうか?詳しい説明をいただきありがとうございます。

Notes_test.txt の入力ファイルの例は次のとおりです。

This is note 1

It has some notes

--------------------------------------------------

This is note 2

It has some more notes

出力は2つのファイルでなければなりません。

This is note 1.md
This is note 2.md

コマンドラインで使用するスクリプトは次のとおりです。

csplit Notes_test.txt -f_ -z -b'%03d.md' /--------------------------------------------------/1 {*} && sed -i '/./,$!d' *.md && for f in *.md
    do
    f1=$(head -n1 "$f")
    mv -n "$f" "$f1.md"
    done

これはこれまでのコマンドの私の理解です。

-fPREFIX 出力ファイル名プレフィックスとして PREFIX を使用します。この場合、下線は「_」で指定されますが、私の考えではこれは単にプレースホルダーです。

-zは長さ0の出力ファイルの生成を抑制します。そうでなければ、csplitは元のファイルを分割し、各実行の終わりに空のファイルを生成するので、これが必要だと思います。

-bSuffix SUFFIX を出力ファイル名の接尾辞として使用します。この場合:「md」

%03dは、ファイル名のプレースホルダとして3桁の数字を使用します。 FelixJNの提案に従って、3の前に0を追加しました。

/------------------------------------------------- - / 1は、「-」行の下の2行を分割するための区切り文字を指定します(0から計算)。

{*} は bash にファイルが終了するまで分割を実行するように指示します。 Felixが指摘したように、「{n}」は実行する分割数です。この場合、「*」はできるだけ行うことを意味します。

&& は、前のコマンドが完了した後に次のコマンドを実行することを意味します。

sed -i は、sed に特定のサフィックス '/./,$!d' を持つファイルで動作するように指示します。これは「ファイルの先頭の空行を削除する」を意味します。説明をくれたFelixにもよろしくお願いします。 sedの作業範囲:「.」はすべての文字を意味するため、文書に表示される最初の文字を指定します。空白行には文字がないため、範囲を定義した後に負の記号「!」を適用する必要があります。範囲は、文字列 "start" と "end" の間にコマンドを適用するために /"start"/,/"end"/ パターンとして定義されます。 $ は最後の行を参照するため、範囲はドキュメント内の空でないすべての行です。否定を適用するには、「NOT」を意味する「!」を使用します。つまり、sed に前の範囲から逆の値を選択するように指示します。この場合、最初の行の前のすべての行にすべての文字を含めることができます。その後、「d」はこの行を削除します。

*.md は「接尾辞 .md を持つすべての名前」を意味します。

f1=$(head -n1 "$f") は次のことを意味します: f1 をファイルの最初の行として定義します ("head" は "最初の行" を意味します)。これは、新しいファイル名(サフィックスを除く)のプレースホルダ(スクリプトの次の行)になる変数シンボル「$」を使用して「f1」を定義することによって行われます。 "head"は通常、各ファイルの最初の10行を出力するbashコマンドです。 head [OPTION]... [FILE]... オプション -n1 は、1 行だけ出力するように指定します。ここで、「$f」は特定のファイルを指定するのではなく、「すべてのファイル」を指定します。スペースが無視されるように、「$ f」の周りには引用符が必要です(そうでない場合、$ fはスペースをフィールド区切り文字として使用し、ファイルをさらに分割します。以下の参照リンクを参照)。

mv -n "$f" "$f1.md" は、各ファイルの名前を "f1.md" に変更することを意味します。

bashコマンド「mv」はオプションと引数を使用します:mv [OPTION] ... [-T] SOURCE DEST、つまり「SOURCEをDESTに名前変更」です。 -nオプションは、--no-clobber "既存のファイルを上書きしない"を示します。これは、同じ最初の行(コメント)を持つファイルが存在しないようにするためだと思います。

バラよりhttps://www.tutorialspoint.com/unix_commands/csplit.htmUNIXのような操作のためのcoreutilsは次の場所にあります。https://www.gnu.org/software/coreutils/manual/coreutils.pdf そしてhttps://www.howtoforge.com/linux-csplit-command/Q2.正規表現を使ってファイルを分割する方法は?そしてスペースやその他の特殊文字が原因でシェルスクリプトが停止するのはなぜですか? いつ二重引用符が必要ですか?

ベストアンサー1

ご理解いただいた部分には問題がないようですので、このsed部分に集中させていただきます。

範囲

sed次のように、anをa(つまり、行の最初の項目)に置き換えると(s置換)、たとえば11行から20行までの範囲内でコマンドを実行できます。AB

sed '11,20s/A/B/'

/start/,/end/文字列との間にコマンドを適用するために、パターンマッチングによって範囲を定義することもできます。startend

あなたの場合は/./,$

Aは.すべての文字を意味し、空白行には文字がないため、行が空でない場合にのみ適用されます。 $最後の行だけが引用されるため、文書全体に対してこれを行いますが、先頭の空白行はスキップされます。

!動作します。これは「NOT」を意味します。つまり、前の範囲から反対の値を選択します。この場合、最初の行の前のすべての行に文字があります。

dその後、この行を削除してください。


'{*}'のもう一つの意見ですcsplit'{n}'は実行する分割数で、アスタリスクは単にできるだけ多くの分割を意味します。また、5回だけ分割することもできます。

%3d%03dゼロパディングされた3桁の数字を表示するために使用しないことをお勧めします。これによりソートが簡単になります。

おすすめ記事