簡體   English   中英

使用sed在指定位置替換大於指定數的數

[英]Using sed to replace a number greater than a specified number at a specified position

我需要編寫一個腳本來替換所有大於以下位置的指定數字的數字。

1499011200 310961583 142550756 313415036 146983209

如果第二項的值超過 300000000,我在這里編寫一個腳本。我需要將整行替換為我想要的值,例如

1499011200 250000000 XXXX XXXX XXXX

我希望我已經把我的問題說清楚了。

提前致謝

這可能對你有用(GNU sed):

sed -r '/^\S+\s+(300000000|[1-2][0-9]{8}|[0-9]{1,8})\s/!c change' file

如果小於或等於300000000 ,則保留它,否則更改它。

或者使用替換:

sed '/^\S\+\s\+\(300000000\|[1-2][0-9]\{8\}\|[0-9]\{1,8\}\)\s/!s/^\(\S\+\s\+\).*/\1250000000 XXXX XXXX XXXX/' file

這是可行的,但並不簡單。 (≥以 0 結尾的數字比 > 更容易。)

讓我們從一個較小的數字開始。

我們如何匹配大於 30 的數字?

  • 大於 30 但小於 40 的兩位數,

     \b3[1-9]\b
  • 40 或更大的兩位數,

     \b[4-9][0-9]\b
  • 位數更多的數字也更大。

     \b[1-9][0-9]\{2,\}\b

使用交替來匹配所有情況。

\b\(3[1-9]\|[4-9][0-9]\|[0-9]\{3,\}\)\b

300000000 類似,但工作量更大。 在這里,為了便於閱讀,我添加了空格,但您需要在sed正則表達式中刪除它們。

\b \( 30000000[1-9]
   \| 3000000[1-9][0-9]
   \| 300000[1-9][0-9]\{2\}
   \| 30000[1-9][0-9]\{3\}
   \| 3000[1-9][0-9]\{4\}
   \| 300[1-9][0-9]\{5\}
   \| 30[1-9][0-9]\{6\}
   \| 3[1-9][0-9]\{7\}
   \| [4-9][0-9]\{8\}
   \| [1-9][0-9]\{9\}
\) \b

在 awk 中:

$ awk '$2>300000000{for(i=3;i<=NF;i++)$i="XXXX"}1' file
1499011200 310961583 XXXX XXXX XXXX

解釋:

$ awk '                 # using awk
$2>300000000 {          # if the second value is greater than ...
    for(i=3;i<=NF;i++)  # for each value aftef the second
        $i="XXXX"       # replace it with XXXX
}1' file                # output

雖然這是一個古老的問題,但值得補充的是,這也可以使用條件來處理:

  • FreeBSD/蘋果操作系統:
    sed -E '/^[0-9]+ +30{8} /, s/^([0-9]+) +([3-9][0-9]{8,}|[0-9]{10.}).*/\1 250000000 XXXX XXXX XXXX/'
  • Linux:
    sed -r '/^[0-9]+ +30{8} /, s/^([0-9]+) +([3-9][0-9]{8,}|[0-9]{10.}).*/\1 250000000 XXXX XXXX XXXX/'

解釋

我們將偷偷摸摸地處理嚴格的“大於”!

我們在命令前加上一個條件,告訴sed處理第二個字段中沒有300000000 的行。 這意味着我們不必擔心匹配 300000001 或 300010000 而不是 300000000。如果一條線通過這個條件,那么(並且只有那時!)我們將繼續並替換any number followed by 300000000 or more followed by anything ,通過the first number (only), followed by " 250000000 XXXX XXXX XXXX"

換一種說法:

如果第二個字段正好是 300000000,則條件意味着什么都不會發生。 否則,如果它小於 300000000,那么它將與正則表達式“查找”部分不匹配,因此什么也不會發生,否則它將進行替換。

開關:

-E / -r告訴sed使用現代正則表達式。 這封信在不同版本的 *nix 之間有所不同,所以它可能是別的東西。 這是此選項最常用的兩個字母。 查看man sed以檢查您的系統需要什么。

健康)狀況:

這很容易。 如果出現以下情況,將處理該行:

  • ^從行的開頭....
  • [0-9]+ +一些大於 1 的數字字符,后跟大於 1 個的空格(您的第一個字段和列間距)...
    其次是:
  • 30{8} 3 后跟恰好 8 個零,后跟一個空格。 我們需要空間,否則它也會匹配,例如 300000000500。
  • /! ! 條件結束后表示“僅在不滿足此條件時才處理命令。

如果一行符合這個條件,那么我們在第二個字段中就有一行正好是 300000000,並且sed將始終保持該行不變。 如果沒有,它將嘗試找到一個匹配項並替換它....

正則表達式替換命令:

由於上述條件,只有在第二個字段正好是 300000000 時才會執行此命令。 所以我們可以假設已經檢查並查看替換操作,如果它在第二個字段中不包含正好 300000000:

  • s查找/替換....
    匹配並替換此表達式,如果在行中找到它(否則什么也不做):
  • ^([0-9]+) +查找行首,后跟任意數量 >1 的數字,然后是任意數量 >1 的空格。 這是第一個字段的內容。 (...)是一個分組,它告訴正則表達式記住它包含的匹配文本部分——這將是第一個字段——有可能在替換操作中重新使用。 (如果匹配成功,我們希望在更改的行中包含第一個字段的值)。 之后還必須...
  • ([3-9][0-9]{8,}|[0-9]{10,}).*僅匹配包含 3-9 后跟 8 位數字或任何 9 位以上數字的第二個字段,然后是行尾的任何其他內容。 請記住*是“貪婪的”並且會匹配所有可能的內容,因此我們不必明確地說“到行尾”,它無論如何都會這樣做。 我們也不需要匹配第二個字段之后的空格,因為*+是貪婪的,它們會匹配所有可能的數字。 所以我們告訴sed匹配任何包含“(行首)(數字)(空格)(數字 >= 300000000)(任何東西)”的行,並記住第一個數字。 盡管該模式在理論上可以匹配並替換精確值 300000000,但它永遠不會,因為我們事先用條件排除了這種可能性。 另請注意,我們最后需要.* ,因為sed僅替換它匹配的內容 - 如果我們將其遺漏,它不會替換該行的其余部分,它只會替換它實際匹配的文本 - 第一個第二個字段——這不是我們想要的。
    如果該行與該表達式匹配,則將匹配的文本(將是整行)替換為:
  • \1 250000000 XXXX XXXX XXXX替換字符串中的\1是“反向引用”。 這意味着,“將第一個匹配組的內容放在這里”。 所以這告訴sed用第一個字段的內容替換整行(因為那是它匹配的內容),然后是一個空格,然后是“250000000 XXXX XXXX XXXX”。

為了完整起見,如果該行可以有前導空格,那么命令將是:

sed -E '/^ *[0-9]+ +30{8} /, s/^( *[0-9]+) +([3-9][0-9]{8,}|[0-9]{10.}).*/\1 250000000 XXXX XXXX XXXX/'

(前導空格,如果有的話,分組內,所以我們在進行替換時保留它們,為了美觀。否則它們會丟失)

完畢。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM