删除模式之前的所有内容

4

我正在尝试清理一个文本文件。

我想删除在第一个12位数字之前的所有内容。

1:0:135103079189:0:0:2:0::135103079189:000011:00
A:908529896240:0:10250:2:0:1:
603307102606:0:0:1:0::01000::M

期望输出结果:

135103079189:0:0:2:0::135103079189:000011:00
908529896240:0:10250:2:0:1:
603307102606:0:0:1:0::01000::M

这是我的命令,但似乎没有起作用。
sed '/:\([0-9]\{12\}\)/d' t.txt
5个回答

2

请尝试按照以下步骤进行。

awk --re-interval 'match($0,/[0-9]{12}/){print substr($0,RSTART)}' Input_file

由于我使用的是旧版本的 awk,因此我正在使用 --re-interval。如果您使用的是新版本,则可以将其删除。


2

sed命令中的d会删除匹配给定正则表达式的整行,如果你只想搜索和替换行中的部分内容,则需要使用s命令...但是,对于给定的问题,sed不适用,因为它不支持非贪婪的正则表达式。

你可以使用perl代替。

$ perl -pe's/^.*?(?=\d{12}:)//' ip.txt
135103079189:0:0:2:0::135103079189:000011:00
908529896240:0:10250:2:0:1:
603307102606:0:0:1:0::01000::M
  • .*? 匹配尽可能少的零个或多个字符
  • (?=\d{12}:) 只有在后面跟着以 : 结尾的 12 位数字时才匹配
  • 使用 perl -i -pe 进行原地编辑


一些可能的特殊情况

$ # this is matching part of field
$ echo 'foo:123:abc135103079189:23:603307102606:1' | perl -pe's/^.*?(?=\d{12}:)//'
135103079189:23:603307102606:1
$ # this is not matching 12-digit field at end of line
$ echo 'foo:123:135103079189' | perl -pe's/^.*?(?=\d{12}:)//'
foo:123:135103079189

$ # so, add start/end of line matching cases and restrict 12-digits to whole field
$ echo 'foo:123:abc135103079189:23:603307102606:1' | perl -pe 's/^(?:.*?:)?(?=\d{12}(:|$))//'
603307102606:1
$ echo 'foo:123:135103079189' | perl -pe's/^(?:.*?:)?(?=\d{12}(:|$))//'
135103079189

1
这可能适用于您(GNU sed):

sed -n 's/[0-9]\{12\}/\n&/;s/.*\n//p' file

我们只想打印特定的行,所以使用-n选项关闭自动打印。如果一行包含12位数字,则在其前插入换行符。删除任何换行符及其之前的字符并打印结果。
如果要按原样打印不包含12位数字的行,请使用:
sed 's/[0-9]\{12\}/\n&/;s/.*\n//' file

问题的关键是识别多字符字符串的开始,插入唯一标记并删除唯一标记之前和包括唯一标记在内的所有字符。由于sed使用换行符来分隔行,只有用户可以将换行符引入模式空间,因此换行符将始终是唯一的。

1
你又一次提出了一个我没想到的 sed 解决方案。太棒了! - PesaThe

0

借鉴@Sundeep的好答案,如果你想使用greppcregrep(macOS / BSD),可以尝试:

$ grep -oP '^(?:.*?:)?(?=\d{12})\K.*' file

或者

$ pcregrep -o '^(?:.*?:)?(?=\d{12})\K.*' file

\K会忽略模式后面的所有内容。


0

备选方案 - 我觉得你的数据可能太脏了,无法通过快速的sed修复。但是如果通常情况下它们与你的样本数据相似,那么肯定可以选择其中一个sed等答案。然而,如果你想更加具体地处理它,你可以建立一组命令来确保这些值。我喜欢在调试时这样做,而且速度不紧急。

拿这个小代码示例来说,你可以用其他方法来完成,但我正在获取字符串的每个部分的值,并且我知道顺序是连续的。然后,你可以设置控件来确定要保留哪些部分,并构建出每行的新字符串。这种方法可能有点过度,但有时候这是更好的长期方法。

#!/bin/bash
while IFS= read -r line ;do
        IFS=':' read -r -a array <<< "$line"
        for ((i=0; i<${#array[@]}; i++)) ;do
                echo "part : ${array[$i]}"
        done
done < "test_data.txt"

然后,您可以按照自己的意愿重新构建数据,并更轻松地了解每个步骤发生的情况。

part : 1
part : 0
part : 135103079189
part : 0
part : 0
part : 2
part : 0
part :
part : 135103079189
part : 000011
part : 00
part : A
part : 908529896240
part : 0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接