如何在Linux中替換大型單行文字檔案中的字串?


有些軟體在處理之前會將整個輸入檔案載入到記憶體中。如果輸入檔案包含非常長的字串,則如果記憶體不足以容納整個字串,軟體可能會崩潰。

我們將探討在Linux中更改非常大的單行檔案中單個字元的方法。一些應用程式無法處理非常大的單行檔案,因此我們將研究我們的選擇。

目標檔案

一些現代JavaScript框架將所有程式碼壓縮到單個語句中。假設我們有一個名為original.js的JavaScript單行程式碼,其中包含錯誤。它呼叫了“fliter”而不是“filter”。我們將在下一節中糾正此錯誤。

使用trsed

我們可以使用tr將該行分成兩部分,然後我們可以使用sed將第一部分替換為第二部分。

分割長行

我們通常使用sed -i替換單行,但是sed會嘗試將整個檔案載入到RAM中。為了克服這個問題,讓我們將我們的行分成多個較小的行,然後將它們傳遞給sed。最後,將結果重新組合在一起。

在Linux中,預設情況下,行用
換行符分隔。在我們的例子中,
換行符被替換為
換行符並輸入到sed中。我們必須選擇不在我們想要更改的行中的元素。此外,替換後輸出應該相對較短。

如果我們想將單行分成多行,我們可以使用一個名為tr的命令,它可以單獨處理每個字母。例如,如果我們想用換行符替換每個空格,我們可以鍵入tr'' '
',其中n代表任意數量的空格。

要將;替換為
,使用以下命令:

命令

$ echo "This is line one;This is line two" | tr ";" "
"

輸出

This is line one
This is line two

如果我們的文件中包含任何換行符,我們應該將“;”替換為“
”和“
”替換為“;”。這樣做將允許我們保持原始換行符序列不變。然後我們將執行tr ";" "
"; 將第一行轉換為單個換行符序列,並執行tr "
" ";" 將第二行轉換為單個換行符序列。

我們將向輸入新增換行符,這意味著我們需要將t引數替換為反向引數。所以假設我們要將每個;替換為
,以及每個
替換為;。然後我們只需編寫如下內容:

命令

$ echo "This is line one;This is line two" | tr ";
" "
;" | tr "
;" ";
"

輸出

This is line one;This is line two

我們可以看到,我們的輸入是相同的。

使用awk

除了sed之外,還有其他程式可以替換檔案中的字串。我們可以使用awk及其gsub函式執行這些步驟。這將是一個兩步過程,用於設定awk的行分隔符並替換字串。

更改行分隔符

我們可以用任何不是我們試圖分割的字串一部分的字元替換預設的換行符(
)。例如,如果我們想將輸入分成單詞,我們可以用下劃線(_)替換換行符。

要在awk中使用不同的行分隔符,我們將在BEGIN塊中將RS(記錄分隔符)設定為所需的字元。例如,如果我們想使用分號作為我們的換行符分隔符,我們將設定RS=";”。讓我們來看一個例子:

命令

$ echo "This is line one;This is line two" | awk 'BEGIN{RS=";"}{print}'

輸出

This is line one
This is line two

正如上一節中提到的,我們必須生成與輸入匹配的結果。即使awk使用“;”字元分割行,結果也必須與原始輸入匹配。我們可以看到awk的printf函式打印出原始輸入中不存在的新行。

讓我們改用printf函式,這樣就不會新增換行符:

命令

$ echo "This is line one;This is line two" | awk 'BEGIN{RS=";"}{printf "%s", $0}'

輸出

This is line oneThis is line two

我們可以看到,我們只缺少“;”字元。我們知道所有行都以行分隔符開頭,除了第一行。因此,讓我們在所有行之前新增“;”字元,除非它是第一行:

命令

$ echo "Thsi is line one;This is line two" | awk 'BEGIN{RS=";"}{ if (NR != 1) { printf "%c", RS } printf "%s", $0 }'

輸出

This is line one;This is line two

我們使用NR變數來確定我們當前在輸入檔案的哪個位置,然後使用RS變數列印換行符。

替換字串

我們已經瞭解瞭如何使用awk(和sed)使用任何非換行符字元將行分割成欄位。現在讓我們看看如何用另一個文字替換文字文件中的一行。

要使用awk從檔案中刪除一個單詞,我們將使用gensub函式。此函式的工作方式類似於sed的替換命令。它採用兩個引數;第一個是正則表示式,第二個是我們想要替換模式的內容。我們將使用上一示例中的相同程式碼來執行此操作。

我們將重複之前所做的操作。讓我們將“.fliter()”替換為“.filter()”。

$ awk 'BEGIN{RS=";"} {
   gsub("\.fliter\(", ".filter(")
   if (NR != 1) {
      printf "%c", RS
   }
   printf "%s", $0
   }' < original.js > fixed.js

請注意,當我們跳脫字元時,sed之間存在差異。我們還需要轉義“(”字元,並且需要使用兩個反斜槓。

結論

我們研究了兩種在極長的單行文字中替換字串的方法。

我們已經瞭解瞭如何使用sed操作檔案,但是我們也學習瞭如何使用awk操作檔案。在這個例子中,我們使用這兩個工具操作相同的輸入。

更新於:2022年12月1日

866 次瀏覽

啟動您的職業生涯

透過完成課程獲得認證

開始
廣告
© . All rights reserved.