如何使用sed或awk删除模式后的某些字符



我有一个文本文件,其中包含许多行,格式如下

001_A.wav;112.680;115.211;;;Ja. Hello; Hi:

我的目标是清理;;;之后的任何东西。意味着删除以下字符,;()~?

我知道我可以做一些类似sed 's/[,.;()~?,]//g'的事情。然而,如果我这样做,它会给我一些类似的东西

001_Awav112.680115211Ja Hello Hi

然而,我想只在;;;之后删除这些字符,这样我就会得到

001_A.wav;112.680;115.211;;;Ja Hello Hi

我该如何完成这项任务?

第一个解决方案: 请您尝试以下内容,用GNUawk中显示的示例编写和测试(其中假设;;;在行中出现一次(。

awk '
match($0,/.*;;;/){
laterPart=substr($0,RSTART+RLENGTH)
gsub(/[,.:;()~?]/,"",laterPart)
print substr($0,RSTART,RLENGTH) laterPart
}'  Input_file

解释:添加以上详细解释。

awk '                                  ##Starting awk program from here.
match($0,/.*;;;/){                     ##Using atch function to match everything till ;;; here.
laterPart=substr($0,RSTART+RLENGTH)  ##Creating variable laterPart which has rest of the line apart from matched regex part above.
gsub(/[,.:;()~?]/,"",laterPart)      ##Globally substituting ,.:;()~? with NULL in laterPart variable.
print substr($0,RSTART,RLENGTH) laterPart ##Printing sub string of matched regex and laterPart var here.
}' Input_file                          ##Mentioning Input_file name here.


第二个解决方案:如果行中多次出现;;;,并且您希望替换所有字段中的字符,则在第一次出现;;;之后,请尝试以下操作。

awk 'BEGIN{FS=OFS=";;;"} {for(i=2;i<=NF;i++){gsub(/[,.:;()~?,]/,"",$i)}} 1' Input_file

您可以使用

sed ':a; s/(;;;[^,.:;()~?,]*)[,.:;()~?,]/1/; ta' file > newfile
sed ':a; s/(;;;[^[:punct:]]*)[[:punct:]]/1/; ta' file > newfile

详细信息

  • :a设置标签
  • (;;;[^,.:;()~?,]*)[,.:;()~?,]匹配并捕获到组1中的;;;子字符串,然后是除,.:;()~?,字符之外的任何零个或多个字符,然后仅匹配,.:;()~?,集合中的一个字符
  • [^[:punct:]]*匹配除标点符号字符以外的任何0个或多个字符
  • [[:punct:]]匹配任何标点符号字符
  • 1为替换,第1组内容
  • ta在成功替换时分支回a标签

请参阅在线sed演示:

s='001_A.wav;112.680;115.211;;;Ja. Hello; Hi:'
sed ':a; s/(;;;[^,.:;()~?,]*)[,.:;()~?,]/1/; ta' <<< "$s"
# => 001_A.wav;112.680;115.211;;;Ja Hello Hi
sed ':a; s/(;;;[^[:punct:]]*)[[:punct:]]/1/; ta' <<< "$s"
# => 001_A.wav;112.680;115.211;;;Ja Hello Hi

没有正确阅读您的问题,但我现在已经更改了。

我建议使用perl,因为它有查找组。

$ perl -pe 's/^((?:(?!;;;).)*;;;)|[:,.;()~?,]/1/g' file.txt
  • ^是该行的开头
  • ((?:(?!;;;).)*;;;)[^;]*的字符串等价物,并确保找到第一个;;;,并将其分组在1
  • CCD_ 26选择字符CCD_。(因此在其中留下"Ja"(

您可以将一些sed命令与组合使用

echo '001_A.wav;112.680;115.211;;;Ja. Hello; Hi:' |
sed 's/;;;/;;;nr/' |
sed  '/^r/ s/[,;():~?]//g' |
sed -z 's/;;;nr/;;;/g'

不同的GNUAWK解决方案:

echo "001_A.wav;112.680;115.211;;;Ja. Hello; Hi:" | awk 'BEGIN{FS=OFS=";;;"}{print $1,gensub(/[,;()~?]/,"","g",substr($0,length($1)+1))}'

输出:

001_A.wav;112.680;115.211;;;Ja. Hello Hi:

这假设您的描述优先于示例(仅删除,;()~?(。说明:我使用;;;作为分隔符,然后输出分隔符Iprint第1列(;;;之前的内容(,并通过查找其开头为第1列的长度加1来获得其余部分,然后从该部分删除所有指定字符并打印它。如果示例优先于描述,那么您可以使用[[:punct:]]字符集,即:

echo "001_A.wav;112.680;115.211;;;Ja. Hello; Hi:" | awk 'BEGIN{FS=OFS=";;;"}{print $1,gensub(/[[:punct:]]/,"","g",substr($0,length($1)+1))}'

将给出

001_A.wav;112.680;115.211;;;Ja Hello Hi

最新更新