2

如何使用此命令:

perl -pi -e 's/[^[:ascii:]]/#/g' file

仅将偏移量 A 处的字符更改为每行的偏移量 B?

4

2 回答 2

7

在保留我没有正确理解您的问题的情况下,如果偏移量 A 和 B 是 5 和 10,那么它应该是:

  perl -pi -e 's/(?<=.{5})(?<!.{10})[^[:ascii:]]/#/g' file

解释:

   [^[:ascii:]]  <- the character which is looked for
   (?<=.{5})     <- if at least 5 chars were before (offset 5)
   (?<!.{10})    <- but no more than 10 characters before (offset 10)

构造:

   (?<= ...) and (?<! ...)

被称为正面和负面的lookbehinds,它们是零与断言。(你可以用谷歌搜索它们,参见perlre的 Look-Around Assertions部分)


附录 1substr()你在标题 中提到,我先忽略了。当然,这也可以:

  perl -pi -e 'substr($_,5,10)=~s/[^[:ascii:]]/#/g' file 

的描述substr EXPR,OFFSET,LENGTH可以在 perldoc中找到。这个例子很好地说明了substr()作为左值的使用。


附录 2 更新此帖子时,Grrrr添加了相同的解决方案作为答案,但他的解决方案领先一分钟!(所以他应该得到战利品)

问候

rbo

于 2012-06-28T09:14:08.767 回答
7

除了橡胶靴的答案之外,您还可以对子字符串而不是整个字符串进行操作:

perl -pi -e 'substr($_, 5, 5) =~ s/[^[:ascii:]]/#/g' file

为了显示:

perl -e 'print "\xff" x 16' | \
perl -p -e 'substr($_, 5, 5) =~ s/[^[:ascii:]]/#/g' | \
hd

将打印

ff ff ff ff ff 23 23 23  23 23 ff ff ff ff ff ff

在这段代码中,第一个偏移量是从 0 开始的,您必须使用长度而不是第二个偏移量,所以它将是 substr($_, A-1, B-A).

于 2012-06-28T09:37:38.333 回答