如何替换列中的文本

如何替换列中的文本

我有一个巨大的文件(超过 2 GB),其中数据如下所示。

12,324,32342,E:fsdsf,23432,34534,45345,324

13,3224,342,E:werwefsdsf,23432,34534,45345,324

121,3244,33442,E:,23432,34534,45345,324

在这里,我需要替换第四列中所有遇到E:空格的地方"",但无论它在后面找到字符串E:,都应该保持原样。

预期输出为:

12,324,32342,E:fsdsf,23432,34534,45345,324

13,3224,342,E:werwefsdsf,23432,34534,45345,324

121,3244,33442,,23432,34534,45345,324

答案1

你的语法是几乎正确的。要测试 中的字符串相等性awk,请使用双等号:==。到指定一个值,使用单个等号。

所以使用if ($4 == "E:")你应该会得到你想要的结果。

完整的命令如下所示。请注意,与您使用的命令只有一个字符不同;这是你唯一的错误:

awk -F , '{ if ($4 == "E:") $4="";}1' OFS=, data.final

为了展示一些不同的语法和不同的方法,以下版本是完全等效的:

awk -F, -v OFS=, '$4 == "E:" { $4 = "" }; 1' data.final

awk 'BEGIN { FS=OFS="," }; $4 == "E:" { $4 = "" }; {print}' data.final

awk -F, -v OFS=, '{sub( /^E:$/, "", $4); print}' data.final

关于上述事项的注意事项:

  1. 如果您的整个代码块只是一个 if/then,您可以仅使用条件作为代码块的过滤器。因此$4 == "E:" {$4 = ""}完全等同于{if ($4 == "E:") {$4 = ""}}
  2. 将“then”语句括在代码块中是一种很好的做法,即使只有其中一个语句,即if ($4 == "E:") {$4 = ""}而不是if ($4 == "E:") $4 = "";
  3. -F设置的值FS,并可-v用于在awk考虑第一个文件的第一行之前设置任何变量的值。(您可能知道这一点。)您也可以使用块BEGIN来做同样的事情;当您想让脚本awk独立时,值得了解这一点。
  4. 1打印行 in 的原因是它是一个始终评估为 true 的条件(过滤器),并且当没有代码块附加到过滤器时的awk默认操作是 to 。所以它本身就相当于or或者 只是。awkprint $011 {print}1 {print $0}{print}
  5. 在我的最后一个变体中,我使用一个函数将正则表达式(字符串开头、字符串结尾)sub替换为in 。/^E:$/E:""$4

由于该sub函数返回进行的替换数(1 或 0;用于gsub进行多个替换),因此您可以通过在sub函数结果中添加 1 来解决此问题,以确保您拥有始终为真的模式,因此无论是否进行替换,都会打印结果行。这是高尔夫版本的代码,如果您将其放入随后要维护的脚本中,则不建议初学者使用:

awk -F, -v OFS=, 'sub(/^E:$/,"",$4)+1' data.final

:)

答案2

sed

sed -r 's/^([^,]+,[^,]+,[^ ]+,)E:(,)/\1\2/' file.txt

如果第四个逗号分隔字段仅包含 ,则该字段将为空白E:

例子:

% cat file.txt
12,324,32342,E:fsdsf,23432,34534,45345,324
13,3224,342,E:werwefsdsf,23432,34534,45345,324
121,3244,33442,E:,23432,34534,45345,324

% sed -r 's/^([^,]+,[^,]+,[^ ]+,)E:(,)/\1\2/' file.txt 
12,324,32342,E:fsdsf,23432,34534,45345,324
13,3224,342,E:werwefsdsf,23432,34534,45345,324
121,3244,33442,,23432,34534,45345,324

答案3

假设您的文件名为file,您可以尝试以下操作:

while read -r line; 
do 
var="$(echo "$line" | cut -d ',' -f 4)";

  if [[ "$var" = "E:" ]]; then echo "$line" | sed s/"$var"/''/g ; 
  else echo "$line";
  fi; 

done < file

或者:

while read -r line; do var="$(echo "$line" | cut -d ',' -f 4)"; if [[ "$var" = "E:" ]]; then echo "$line" | sed s/"$var"/''/g ; else echo "$line";fi; done < file

解释:

  1. while read -r line;逐行读取文件
  2. var="$(echo "$line" | cut -d ',' -f 4)";将第 4 个位置的字符串分隔,成变量var
  3. if [[ && "$var" = "E:" ]]; then echo "$line" | sed s/"$var"/' '/g ;如果$var恰好有字符串E:则将sed s/"$var"/''/g ;其替换为空白""
  4. else echo "$line";否则它会按原样打印行

例子输出(正如问题所预期的那样):

  • file:

    $ cat file
    12,324,32342,E:fsdsf,23432,34534,45345,324
    
    13,3224,342,E:werwefsdsf,23432,34534,45345,324
    
    121,3244,33442,E:,23432,34534,45345,324
    
  • 运行命令:

    $ while read -r line; do var="$(echo "$line" | cut -d ',' -f 4)"; if [[ "$var" = "E:" ]]; then echo "$line" |sed s/"$var"/' '/g ; else echo "$line";fi; done < file
    12,324,32342,E:fsdsf,23432,34534,45345,324
    
    13,3224,342,E:werwefsdsf,23432,34534,45345,324
    
    121,3244,33442,,23432,34534,45345,324
    

>> file2您还可以使用或|tee file2在命令的最后将输出重定向到文件:

while read -r line; do var="$(echo "$line" | cut -d ',' -f 4)"; if [[ "$var" = "E:" ]]; then echo "$line" |sed s/"$var"/' '/g ; else echo "$line";fi; done < file | tee file2

相关内容