次のテキストファイルがあります。
#unimportant comment
#possible more unimportant comments
#info1 info2 info3 ,importantname1
importanttext1
#info1 info2 info3 ,importantname2
importanttext2
#info1 info2 info3 ,importantname3
importanttext3
各ファイルを別々のファイルに分割したい。私が本当に必要とするのは、コメントのないURLを抽出することです。コメントを保持することはオプションです。各ファイルの名前をimportantname1.txt、または各コメント行の末尾にカンマを追加して.txtとして指定したいと思います。
したがって、importantname1.txt には次の内容が含まれます。
importanttext1
または多分
#info1 info2 info3 ,importantname1
importanttext1
したがって、行はコメントアウトされたファイル名で抽出および保存されます。この場合、.txtファイル名importantname1.txtが追加されます。
これは、サンプルファイルの各行セットに対して実行する必要があります。コメントを維持することは重要ではありませんが、スクリプトを書くことができるはずです。また、ヘッダー内の不明な数のコメント行も考慮する必要があります。コメント行は常に各importanttextX行の前にあります。
答え1
努力する:
awk -F, '/^#/{f=$NF".txt";cmt=$0; next} {printf "%s\n%s\n",cmt,$0 >f; close(f)}' file
はい
サンプル入力に適用されます。
$ awk -F, '/^#/{f=$NF".txt";cmt=$0; next} {printf "%s\n%s\n",cmt,$0 >f; close(f)}' file
上記を実行すると、ディレクトリに次のファイルがあります。
$ ls
file importantname1.txt importantname2.txt importantname3.txt
新しいファイルの内容は次のとおりです。
$ cat importantname1.txt
#info1 info2 info3 ,importantname1
importanttext1
$ cat importantname2.txt
#info1 info2 info3 ,importantname2
importanttext2
$ cat importantname3.txt
#info1 info2 info3 ,importantname3
importanttext3
どのように動作しますか?
awk は入力ファイルを 1 行ずつ読み込みます。私たちのスクリプトはこれらの行をコメントまたは非コメントに分類します。コメント行の場合、ファイル名とコメントが保存されます。コメントがない場合は、新しいファイルが作成され印刷されます。
`-F,
これは awk に入力フィールド区切り文字としてコンマを使用するように指示します。これにより、ファイル名が常に最後のフィールドになります。
/^#/{f=$NF".txt";cmt=$0; next}
行が始まる場合は、ファイル名と
#
最後のフィールドとして保存します。コメント付きの行全体がとして保存されます。その後、awkにコマンドの残りの部分をスキップし、その行に移動して再起動するように指示します。$NF
.txt
f
cmt
next
printf "%s\n%s\n",cmt,$0 >f; close(f)
コメント以外の行の場合は、最後に見たコメントと
cmt
現在の行を$0
最後に見たファイル名に印刷しますf
。次にファイルハンドルを閉じますf
。
無効なファイル名の防止
ファイル名として使用するフィールドが含まれている場合、/
オペレーティングシステムはファイル名にディレクトリが含まれていると解釈します。これを防ぐには、次のようにすべてをusing/
に置き換えることができます。-
gsub(/\//, "-", f)
awk -F, '/^#/{f=$NF".txt";gsub(/\//, "-", f); cmt=$0; next} {printf "%s\n%s\n",cmt,$0 >f; close(f)}' file
答え2
grep
AとBの組み合わせは、a)コメントされていないすべての行と前のメッセージ1をpingし、b)メッセージコメント行に基づいて出力を分割することによってcsplit
操作を実行できます。grep
grep -v -B1 '^#' file | csplit -z - '/^#/' '{*}'
つまり、-v
先頭に#がある行を抽出せずに^#
、この行の前の行を抽出してください-B1
。次に、-
行の先頭の#ごとに着信パイプ入力を分割し、空のファイルを無視し、-z
できるだけ頻繁にこれを実行します{*}
。
名前の変更は別のステップでなければなりません(csplit
出力名をxx00、xx01 ...に自動割り当て - プレフィックスとサフィックスをそれぞれ変更するには、および-f
オプションを使用してください)。-b
#/bin/bash
for f in xx* ; do
mv "$f" "$( sed -n '2p' "$f" )".txt
done