>我正在尝试使用标准 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 I
和Step 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:match
awk
效用。
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