Regex 仅在sed或awk中匹配后替换空白

Regex 仅在sed或awk中匹配后替换空白,regex,awk,sed,text-processing,Regex,Awk,Sed,Text Processing,我需要修改这组行 00:00 07:45 01. Alva 07:45 14:40 02. White Cliffs 14:40 20:22 03. Ribcage #1 20:22 25:04 04. I am Oidipus 匹配后(可能是点),我需要用破折号-或下划线-替换后面的空白 预期结果: 我已经尝试了以下方法,但结果参差不齐 dummyfile2是我用来存储文本字符串的文件名 给出结果: 00:00 07:45 01._Alva 07:45 14:40

我需要修改这组行

00:00  07:45  01. Alva 
07:45  14:40  02. White Cliffs 
14:40  20:22  03. Ribcage #1 
20:22  25:04  04. I am Oidipus
匹配后(可能是点),我需要用破折号-或下划线-替换后面的空白

预期结果: 我已经尝试了以下方法,但结果参差不齐

dummyfile2是我用来存储文本字符串的文件名

给出结果:

00:00  07:45 01._Alva
07:45  14:40 02._WhiteCliffs
14:40  20:22 03._Ribcage #1 
20:22  25:04 04._I am Oidipus
00:00  07:45 01._Alva
07:45  14:40 02._Whit_Cliffs
14:40  20:22 03._Ribcag_#1 
20:22  25:04 04.__a_Oidipus
我也试着做了以下几件事

sed -i 's/\(\.\)\(\s*\)/\1_/g' dummyfile2 | sed -i 's/\([[:alpha:]][[:space:]]\)\(\s*\)/_/g' dummyfile2
给出结果:

00:00  07:45 01._Alva
07:45  14:40 02._WhiteCliffs
14:40  20:22 03._Ribcage #1 
20:22  25:04 04._I am Oidipus
00:00  07:45 01._Alva
07:45  14:40 02._Whit_Cliffs
14:40  20:22 03._Ribcag_#1 
20:22  25:04 04.__a_Oidipus
最后一个是我能想到的最接近的。(但这不是预期的结果。)

编辑:似乎其他解决方案将只处理空间替换
之后的第一个空间,后续将处理所有空间

awk 'match($0,/[^.]*/){val=substr($0,RSTART+RLENGTH);gsub(/ /,"_",val);print substr($0,RSTART,RLENGTH) val;next} 1' Input_file

00:00  07:45  01._Alva
07:45  14:40  02._White_Cliffs
14:40  20:22  03._Ribcage_#1
20:22  25:04  04._I_am_Oidipus


如果您正在尝试使用
sed
,以下内容可能会对您有所帮助。您不需要使用多个
sed
命令

sed -E 's/\. +/\._/'  Input_file
00:00  07:45  01._Alva 
07:45  14:40  02._White Cliffs 
14:40  20:22  03._Ribcage #1 
20:22  25:04  04._I am Oidipus
更改
sed-E的/\.+/\.\uu/'
sed-E的/\。+/\_/g'
,以防在一行中多次出现
(空格)



如果您对
awk
没有问题,请尝试以下内容

awk '{sub(/\. +/,"._")} 1' Input_file
如果多次出现
,则在上述命令中将
sub
替换为
gsub
。输出如下

00:00  07:45  01._Alva 
07:45  14:40  02._White Cliffs 
14:40  20:22  03._Ribcage #1 
20:22  25:04  04._I am Oidipus
cat Input_file
00:00  07:45  01. Alva 
07:45  14:40  02. White Cliffs 
14:40  20:22  03. Ribcage #1 
20:22  25:04  04.   I am Oidipus
awk '{sub(/\. +/,"._")} 1' Input_file
00:00  07:45  01._Alva 
07:45  14:40  02._White Cliffs 
14:40  20:22  03._Ribcage #1 
20:22  25:04  04._I am Oidipus
使用多个空格测试上述代码:假设
之后有多个空格,那么aboe代码也可以工作。假设您的输入文件如下所示

00:00  07:45  01._Alva 
07:45  14:40  02._White Cliffs 
14:40  20:22  03._Ribcage #1 
20:22  25:04  04._I am Oidipus
cat Input_file
00:00  07:45  01. Alva 
07:45  14:40  02. White Cliffs 
14:40  20:22  03. Ribcage #1 
20:22  25:04  04.   I am Oidipus
awk '{sub(/\. +/,"._")} 1' Input_file
00:00  07:45  01._Alva 
07:45  14:40  02._White Cliffs 
14:40  20:22  03._Ribcage #1 
20:22  25:04  04._I am Oidipus
在这里,我更改了最后一行,在
之后添加了更多空格,现在在运行代码之后,它将用单个
\uu
替换它们,如下所示

00:00  07:45  01._Alva 
07:45  14:40  02._White Cliffs 
14:40  20:22  03._Ribcage #1 
20:22  25:04  04._I am Oidipus
cat Input_file
00:00  07:45  01. Alva 
07:45  14:40  02. White Cliffs 
14:40  20:22  03. Ribcage #1 
20:22  25:04  04.   I am Oidipus
awk '{sub(/\. +/,"._")} 1' Input_file
00:00  07:45  01._Alva 
07:45  14:40  02._White Cliffs 
14:40  20:22  03._Ribcage #1 
20:22  25:04  04._I am Oidipus

awk
救援

$ awk 'BEGIN{FS=OFS="."} {gsub(/ /,"_",$2)}1' file

00:00  07:45  01._Alva
07:45  14:40  02._White_Cliffs
14:40  20:22  03._Ribcage_#1
20:22  25:04  04._I_am_Oidipus

使用GNU sed,您可以这样做:

sed -E ':a;s/(\.\S*)\s+(\S+)/\1_\2/;ta'
示例(添加了一个边缘案例):

POSIX sed兼容:

sed -e ':a' -e 's/\(\.[^[:space:]]*\)[[:space:]][[:space:]]*\([^[:space:]][^[:space:]]*\)/\1_\2/;' -e 'ta' file
sed -e :a -e 's/\(\.[^ ]*\) /\1_/;ta' file

如果您确定行中没有尾随空格,或者希望替换尾随空格,则可以删除第二个catch组(
(…)
\(…)
)以及在任何UNIX框上的任何shell中带有任何awk的
\2

$ awk 'p=index($0,"."){tl=substr($0,p+1); gsub(/ /,"_",tl); $0=substr($0,1,p) tl} 1' file
00:00  07:45  01._Alva
07:45  14:40  02._White_Cliffs
14:40  20:22  03._Ribcage_#1
20:22  25:04  04._I_am_Oidipus
或使用GNU awk匹配第三个参数()和gensub():

使用sed(符合POSIX标准):

如果您只想用一个
\uu
替换连续空格:

sed -e :a -e 's/\(\.[^ ]*\)  */\1_/;ta' file

通过程序文本编辑,您可以这样实现:

forEach line {
  select (after ci ".") { findReplace ci " " "_" }
}
这可能适用于您(GNU-sed):


sed-E的/\s+\有很多很棒的答案。我不熟悉
awk
,但这里有一个简单的解决方案

awk 'BEGIN{FS=OFS="  "} {gsub(/ /, "_", $3); print $0}' InputFile
这是我的
InputFile

00:00  07:45  01. Alva
07:45  14:40  02. White Cliffs
14:40  20:22  03. Ribcage #1
20:22  25:04  04. I am Oidipus
00:00  07:45  01._Alva
07:45  14:40  02._White_Cliffs
14:40  20:22  03._Ribcage_#1
20:22  25:04  04._I_am_Oidipus
这是
awk'BEGIN{FS=OFS=“”}{gsub(//,““,$3);print$0}输入文件之后的
output

00:00  07:45  01. Alva
07:45  14:40  02. White Cliffs
14:40  20:22  03. Ribcage #1
20:22  25:04  04. I am Oidipus
00:00  07:45  01._Alva
07:45  14:40  02._White_Cliffs
14:40  20:22  03._Ribcage_#1
20:22  25:04  04._I_am_Oidipus
说明: BEGIN=这段代码在读取文件之前执行,这意味着所有变量都可以在这里声明

FS=字段分隔符=两个空格(从InputFile中每隔两个连续空格识别一个新字段

OFS=输出字段分隔符=两个空格(在输出中每两个连续空格后识别一个新字段..与Inputdata一样

gsub(//,“quo,$3)
将第3栏中的一个空格“”替换为下划线($3)

最后,打印每一行,直到文件结束

{print $0}
使用Perl

$ perl -pe ' s/(?:\S+)\. (.+)$/$x=$&;$x=~s! !_!g;$x/ge ' whitespace.txt
00:00  07:45  01._Alva
07:45  14:40  02._White_Cliffs
14:40  20:22  03._Ribcage_#1
20:22  25:04  04._I_am_Oidipus

$

如果第一个
后面的文本也包含
s,并且对我来说它看起来像自由文本,那么我看不出任何理由认为它不能包含
s。您不需要第二次反向引用。与
sed-E相同的输出:a;s/(\.\s*)/\1\uu/;ta'文件
@SLePort OP的样本数据中有尾随空格,显然OP不希望尾随空格被下划线替换。我们还可以通过代码
(\s*\)来解释OP的意图
OP希望用一个
替换连续的多个空格。OP处理尾随空格的方式并不明显。这是示例数据,而不是源文件。尾随空格可能是复制和粘贴的结果。@SLePort C&P不会导致这种情况,可能是OP在发布后出现格式错误这是一个安全的方法。谢谢你给我的提示。我会在下一次发布一个问题后再考虑这个问题。