從長文件中提取文字行

從長文件中提取文字行

我有以下文字檔:

#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) grepping 所有未註解的行加上前面的資訊一和 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

相關內容