徐小玉的博客。
分类: LINUX
2017-09-06 17:57:33
aaa 35-38
fffff 68-71,2-75,76-80
fffff 101-105
fffff 106-110
kkkk 35-37
kkkk 38-40
77777 1-8
77777 9-16
77777 39-40
77777 41-42
77777 43-44
77777 45-46
2222 25-26,27-28
上述文本假设其中n条,把有逗号的行第二列中间部分去掉,并且添加符号n,如下所示,perl,awk python分别如何实现
aaa 35-38
fffff 68n80
fffff 101-105
fffff 106-110
kkkk 35-37
kkkk 38-40
77777 1-8
77777 9-16
77777 39-40
77777 41-42
77777 43-44
77777 45-46
2222 25n28
--------------------------
awk '/,/{sub("-.*-","n",$0)}1' file4
awk '/,/{sub("-.*-","n",$0)}{print $0}' file4
1. sub函数
# echo "a b c 2011-11-22 a:d" | awk 'sub(/-/,"",$4)'
a b c 201111-22 a:d
2. gsub函数
# echo "a b c 2011-11-22 a:d" | awk 'gsub(/-/,"",$4)'
a b c 20111122 a:d
sub函数只实现第一个位置的替换,gsub函数实现全局的替换。
3: 1 作何解释?
1 => 1{print $0} => if(1){print $0} => {print $0}
-------------------
awk '{sub(/-.*..*-/,"n",$2)}1' file4
---------
sed 's/-.*-/n/' file4
------perl
#!/usr/bin/perl
use strict;
use warnings;
while(){
y/.//d and s/-.*-/n/;
print;
}
__DATA__
aaa 35-38
fffff 68-71.72-75.76-80
fffff 101-105
fffff 106-110
kkkk 35-37
kkkk 38-40
77777 1-8
77777 9-16
77777 39-40
77777 41-42
77777 43-44
77777 45-46
2222 25-26.27-28
找了不少关于tr的用法,发现最后面附的那个帖子算是比较详细的。 个人测试的结果总结如下: (1)/c表示把匹配不上的字符进行替换. $temp="AAAABCDEF"; $count=$temp=~tr/A/H/c; print "$temp\t$count\n"; 结果:AAAAHHHHH 5 (2)/d:表示把匹配上的字符全部替换 $temp="AAAABCDEF"; $count=$temp=~tr/A/H/d; print "$temp\t$count\n"; 结果:HHHHBCDEF 4 (3)/s:表示如果要替换的字符中出现连续多个一样的字符,则去冗余: $temp="AAAABCDEF"; $count=$temp=~tr/A/H/ds; print "$temp\t$count\n"; 结果:HBCDEF 4 $temp="AAAABCDEF"; $count=$temp=~tr/A/H/cs; print "$temp\t$count\n"; 结果:AAAAH 5 ============================================================= 另外,我再总结一下tr的用处: $count=$temp=~tr/A//; #表示计算$temp中出现A的次数,$temp并不改变值 $count=$temp=~tr/A/A/; #表示计算$temp中出现A的次数,$temp并不改变值 和上面的意思一样的
$temp="AAAABCDEF"; $count=$temp=~tr/[A-Z]/[a-z]/; #表示进行大小写转换 print "$temp\t$count\n";
结果:aaaabcdef 9
如果写成$count=$temp=~tr/[A-Z]/[A-Z]/; 则$temp不会改变,仅统计$temp里面大写字母的个数
结果:AAAABCDEF 9
=================================================================== 下面是转载的内容 =================================================================== 关键词1perl 2tr///
此文完整连结 |
|
Perl 中s/// 和 tr/// 的差别 说真的,要学好 perl 还真的不简单,因为 perl 的程序代码比C来得精简一半1,靠得就是在撰写时的大脑运作。程设师得花更多时间写出精简的 code,同时也要将「语意上的错误」减少到最低,这就是要靠经验的累积。废话不多说,先说s/// 置换的功能,s 是 substitute的意思: s/原来字符串/目的字符串/修饰子 s/// 会默认搜索 $ _,找出「原来字符串」,换成「目的字符串」。该运算符返回匹配的数量或进行替换的数量,如果没有进行任何匹配,则返回0。 ex: 把 Who 换成 What
$str = "Who are you?";
要取得比对成功的个数,可以写 s/// 只会预设置换第一个找到的目标字符串,假若想全部置换,就要加 g 修饰子:
$str = "What a wonderful wonderful world."; 假设比对原来的字符串不分大小写的话,就可加 i 修饰子:
$str = "What a wonderful wonderful world."; 假若我们要将比对到的字符串,前后加上单引号,这在其他语言是困难的事,对perl来说像吃x一样简单,这里一个特殊变量 $& 就是比对到的字符串:
$str = "What a wonderful wonderful world."; s/// 里面的「目的字符串」是可以放入函式的,例如以下几个常用的函数: uc($str) 把$str 全转成大写 lc($str) 把$str 全转成小写 ucfirst($str) 把$str 第一码转成大写 假设我想把找到的结果全转成大写,一般的置换就伤透脑筋了,可是perl提供了不错的解法,但是要使用函数,就得加上 e 修饰子:
$str = "What a wonderful wonderful world.";
如果没加 e 修饰子,则函式会被当成字符串丢出来: 再来比较麻烦的是字符串中的换行 \n,字符串中的换行字符 '\n' 被当成是一个字符来处理,所以假设一个具有换行字符的(多行的的字符串,希望比对时忽略那个换行字符,就要加上 s 修饰子:
$str = "What a wonder\nful wonderful world.";
What a www www world What a www wonderful world
另外比较少见的情形下会用到的 m 修饰子:一般比对时假设要找出字符串结尾的字符串,常会用变换字符 $,在带有换行的字符串中,变换字符 $只会比对最后的换行或是字符串结尾。如果希望 $能取得符合带有换行的字符串中,每个换行都视为结尾的话,就要加 m。这样形容比较抽象,看个范例:
$str = "line123\nline456\nline789";
$str =~ s/\d+$//mg; <== 注意现在加了 m
line <==每个换行符号都视为结尾 写了这么多 s///,现在来说 tr///,tr 的语法和 s 好像一样,其实还差异满大的,tr 主要作为项目列表的置换: tr/原来比对列表/目的比对列表/选项 perl 的 tr把置换的功能再扩张,虽然 s很强,可是也有做不到的事,例如今天要把大写换成小写,「同时」小写也换成大写,s就一筹莫展了,但 tr 可以搞定:
$str = "Aine123\nBine789";
aINE123 同时tr 也可以用来计算字数,只需要把自己换成自己就好,例如以下范例计算$doc出现的数字个数:
$doc="<78>Nov 3 11:20:01 163.17.44.1 crond[30367]: (root) CMD (LANG=C LC_ALL=C /usr/bin/mrtg /etc/mrtg/mrtg.cfg --lock-file /var/lock/mrtg/mrtg_l --confcache-file /var/lib/mrtg/mrtg.ok)"; 这里要注意,上式的 $doc 本身并没有改变,所以如果下一行 print $doc; 得到的结果还会是原字符串。所以如果要取得计算的字数,就得写成这样: $count = $doc=~ tr/0-9/0-9/; tr 还有一个别名,叫作 y/// 所以要把数字0和9互换,可以写成
$doc =~ y/09/90/; 接来看看 tr 的选项,tr 只有三个选项,英文是 perldoc 的说明,我把他的意思用我的话写出来:
c Complement the SEARCHLIST. <== 列表没写到的就补给他右边列表的最后一个字符 来看看范例:
my $text = 'good cheese';
合并以上两个参数 tr/左列表/右列表/c 规则、左列表没有的,就补右清单的东西。
my $text = 'good cheese'; # 结果 _oo____ee_e 如果右清单写了不只一个呢?会怎样?其实补的时候还是只会拿右清单的最后一个
$doc="<78>Nov 3 11:20:01 163.17.44.1 crond[30367]";
# 结果不是英文全都补了右列表的最后一个字符'z' $doc= 当然不能都出简单的范例,来看看这个所以以下范列就可以把字符串中非英文字母a-zA-Z给删掉,成为空白。
$doc="<78>Nov 3 11:20:01 163.17.44.1 crond[30367]: (root) CMD (LANG=C LC_ALL=C /usr/bin/mrtg /etc/mrtg/mrtg.cfg --lock-file /var/lock/mrtg/mrtg_l --confcache-file /var/lib/mrtg/mrtg.ok)";
# 结果 当然还要写一点不一样的,要不然我写这篇就没意思了。现在如果要把变量的结果放到 tr 里,该怎么写?因为tr的清单是在编译时就写完了,如果要在执行期把演算出来的结果放去清单,就要写成这样(可参考 perlop )
eval "tr/$oldlist/$newlist/";
预设缺省是用 $_ 去评估,所以以下范例: 结论,s/// 和 tr/// 还有很多用法,不过两者不太一样,要能活用,得花时间,我也没完全搞清"此"。
原始连结: 精赞部落 note.tcc.edu.tw |