获取字符串中给定字符/模式每次出现之前的字符



>我正在尝试使用标准 bash 工具获取字符串中给定字符/模式每次出现之前的字符,如 grep、awk/gawk、sed ...

Step I:获取每次出现的字符之前的字符:

例:

字符串 1 => :hd:fg:kl:

字符串 2 => :d f:lkjh:

字符串 3 => :glki:l:s:d:

预期成果

结果 1 => dgl

结果 2 => fh

结果 3 => ilsd

我用awk尝试了很多次,但没有成功

Step II:在结果字符串的每个字符之间插入给定字符

带有/的示例

结果 1 => d/g/l

结果 2 => f/h

结果 3 => i/l/s/d

我对这一步有一个尴尬的表达awk -F '' -v OFS="/" '{$1=$1;print}'

我不知道是否可以用awk或sed做Step I,为什么不做一次Step IStep II

亲切问候

怎么样:

awk 'BEGIN{FS=":"}{for(i=1;i<NF;i++){if(i>2)printf"/";printf substr($i,length($i))}print""}' input.txt

输入.txt:

:hd:fg:kl:
:df:lkjh:
:glki:l:s:d:

输出:

d/g/l
f/h
i/l/s/d

解决方案1st: 您能否尝试以下操作,并让我知道这是否对您有帮助。

awk -F":" '
{
for(i=1;i<=NF;i++){
if($i){ val=(val?val:"")substr($i,length($i)) }
}
print val;
val=""
}' Input_file

输出将如下所示。

dgl
fh
ilsd

解决方案 2nd:在输出字符串之间有一个/

awk '
BEGIN{
OFS="/";
FS=":"
}
{
for(i=1;i<=NF;i++){
if($i){
val=(val?val OFS:"")substr($i,length($i))
}}
print val;
val=""
}' Input_file

输出将如下所示。

d/g/l
f/h
i/l/s/d

解决方案3rd:matchawk效用。

awk '
{
while(match($0,/[a-zA-Z]:/)){
val=(val?val:"")substr($0,RSTART,RLENGTH-1)
$0=substr($0,RSTART+RLENGTH)
}
print val
val=""
}'  Input_file

这可能对你有用(GNU sed(:

sed -r 's/[^:]*([^:]):+|:+/1/g;s/B///g' file

将零个或多个非:后跟单个字符后跟一个:或一个单独的:整个行中全局的单个字符替换。然后替换 在每个字符之间插入一个/

Perl 和负面展望:

$ perl -p -e 's/.(?!:)//g' file
dgl
fh
ilsd

这更容易用perl

$ cat ip.txt
:hd:fg:kl:
:df:lkjh:
:glki:l:s:d:
$ perl -lne 'print join "/", /.(?=:)/g' ip.txt
d/g/l
f/h
i/l/s/d
  • /.(?=:)/g获取:之前的所有字符
    • (?=:)是一个前瞻结构
  • 然后使用/作为分隔符字符串打印生成的匹配

与 ERE 一起

sed -E 's#[^:]*(.):#1/#g;s/^.|.$//g' infile

使用 GNU sed:

sed -E 's/[^:]*([^:]):/1/g; s/([^:])//1/g; s/^:///'

第一个命令,s/[^:]*([^:]):/1/g匹配删除多余的字符和冒号(第一个除外(,因此产生如下:

:dgl
:fh
:ilsd

第二个命令s/([^:])//1/g在每个字符之前插入一个/,得到:

:/d/g/l
:/f/h
:/i/l/s/d

最后一个命令s/^:///只是从每行的开头删除:/

d/g/l
f/h
i/l/s/d

您可以使用 gawk 从第二个字符开始遍历每一行。每次迭代器命中冒号时,都会打印前一个字符。

$ awk <file.txt '{for(i=2;i<=length($0);i++) { 
if (substr($0,i,1)==":") printf substr($0,i-1,1);} printf "n";}'
dgl
fh
ilsd

最新更新