[英]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
雖然這是一個古老的問題,但值得補充的是,這也可以使用條件來處理:
sed -E '/^[0-9]+ +30{8} /, s/^([0-9]+) +([3-9][0-9]{8,}|[0-9]{10.}).*/\1 250000000 XXXX XXXX XXXX/'
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.