我有以下文字檔:
#unimportant comment
#possible more unimportant comments
#info1 info2 info3 ,importantname1
importanttext1
#info1 info2 info3 ,importantname2
importanttext2
#info1 info2 info3 ,importantname3
importanttext3
我想將每個文件分解為單獨的文件。我真正需要的是提取未註釋的網址,保留註釋是可選的。我希望每個檔案都被命名為 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 逐行讀取輸入檔。我們的腳本將這些行分類為註釋或非註釋。對於註解行,將儲存檔案名稱和註解。對於非註釋,將建立並列印一個新文件
`-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
。
防止錯誤的檔案名
如果要用作檔案名稱的欄位包含/
,作業系統會將檔案名稱解釋為包含目錄。為了避免這種情況,我們可以將 all 替換/
為-
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
和的組合csplit
可以完成這項工作,方法是 a) grep
ping 所有未註解的行加上前面的資訊一和 b) 根據資訊註解行分割輸出:
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