次のテキスト ファイルがあります。
#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}
行が で始まる場合
#
、最後のフィールド$NF
と、.txt
ファイル名 を保存しますf
。コメント行全体は として保存されますcmt
。次に、awk に残りのコマンドをスキップして、行を最初からやり直すように指示しますnext
。printf "%s\n%s\n",cmt,$0 >f; close(f)
コメント行以外の行については、最後に表示されたコメント
cmt
と現在の行 を、$0
最後に表示されたファイル名 に出力しますf
。次に、 のファイル ハンドルを閉じますf
。
不正なファイル名からの保護
ファイル名として使用されるフィールドに が含まれている場合、OS はファイル名にディレクトリが含まれていると解釈します。これを回避するには、次のようにしてすべてを に/
置き換えます。/
-
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)コメントのないすべての行とその前の info 行を ping し、b) info コメント行に基づいて出力を分割することで、csplit
この作業を実行できます。grep
grep -v -B1 '^#' file | csplit -z - '/^#/' '{*}'
-v
つまり、先頭に # がある行は抽出しません^#
が、そのような行の 1 行前は抽出します-B1
。次に、入力されたパイプ入力を-
行の先頭の各 # で分割し、空のファイルは無視して-z
、できるだけ頻繁にこれを実行します{*}
。
名前の変更は別の手順で行う必要があります ( csplit
outpit に xx00、xx01 などの自動名前が付けられます。それぞれ、-f
および-b
オプションを使用して、接頭辞と接尾辞を変更します)
#/bin/bash
for f in xx* ; do
mv "$f" "$( sed -n '2p' "$f" )".txt
done