【问题标题】:Remove all characters before specific number in Nth column at first match NOT last在第一次匹配时删除第 N 列中特定数字之前的所有字符而不是最后一个
【发布时间】:2021-09-08 14:18:36
【问题描述】:

我正在尝试从数据集中的第 5 列中删除一个随机字符块。

样本数据:

A | 12 | AA | 24 | Test to go and keep 192.168.1.1 > 192.168.2.1 | B

结果应如下所示:

A | 12 | AA | 24 | 192.168.1.1 > 192.168.2.1 | B

到目前为止我有这个:

awk 'BEGIN{FS=OFS="|"} {gsub(".*? 192","", $5 )} 1' file.txt

但是,这会删除最后一场比赛前第 5 列中的所有内容。

代码现在做了什么:

.168.2.11

我需要在第一个匹配之前删除所有内容,而不是最后一个

【问题讨论】:

  • 当前 *awk 不支持非贪婪 (.*?) 匹配,如果您愿意,您可以使用一些内置函数(例如使用 match() 函数)编写自己的 awk 函数匹配其参数中最短的正则表达式,并对 RSTART 和 RLENGTH 进行一些后处理,并与 substr() 结合以删除所需的部分。

标签: linux awk gsub less-unix


【解决方案1】:

使用您展示的示例,请尝试遵循awk 代码。简单的解释是:对于 Input_file 的所有行,将字段分隔符和输出字段分隔符设置为 |。然后在第 5 个字段中用 NULL 全局替换空格和字母。在第 5 个字段之前和之后按照所示示例添加空格,最后打印已编辑/未编辑的当前行。

awk 'BEGIN{FS=OFS="|"} {gsub(/[[:alpha:]]+|[[:space:]]+/,"",$5);$5=" "$5" "} 1' Input_file


编辑:如果您想在第 5 个字段中始终匹配 IP 地址 > IP 地址形式,那么只需尝试以下操作。

awk 'BEGIN{FS=OFS="|"} match($0,/([0-9]+\.){3}[0-9]+ > ([0-9]+\.){3}[0-9]+/){$5=substr($0,RSTART,RLENGTH)} 1' Input_file

【讨论】:

  • @AUSBRIS88,根据您显示的示例,此代码可以正常工作,您能否告诉我它在哪里不工作?
  • 几乎,但是总和仍然缺失。为了简单起见,我简化了数据代码,但我要优化的实际数据集是:A | 12 |机管局 | 24 | Ipv4Header (tos 0x0 DSCP Default ECN Not-ECT ttl 64 id 0 protocol 6 offset (bytes) 0 flags [none] length: 56 192.168.1.1 > 192.168.2.1 | BI 只需要第 5 列显示:192.168.1.1 > 192.168 .2.1
  • @AUSBRIS88,能否请您在问题中提供这些示例,然后让我知道。
  • @AUSBRIS88,我相信我的 EDIT 解决方案对您有用,请检查一次,然后告诉我?
  • 这个答案对我有用!! awk 'BEGIN{FS=OFS="|"} 匹配($0,/([0-9]+\.){3}[0-9]+ > ([0-9]+\.){3} [0-9]+/){$5=substr($0,RSTART,RLENGTH)} 1' Input_file 非常感谢您的分享!我尝试了几个小时才能让它工作
【解决方案2】:

如果文件第 5 列中的 IP 地址总是以某些特定数字开头,例如“192.168.”,那么,您可以使用:awk 'BEGIN{FS=OFS="|"}{$5=substr($5, index($5, " 192.168."))}1' file.txt

【讨论】:

  • 你确定这有效吗? awk: fatal: 1 is invalid as number of arguments for index
  • @tink 谢谢你的指出。我已经修复了错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-04
  • 2011-07-16
  • 2022-11-23
相关资源
最近更新 更多