使用sed删除变量名中的_

时间:2019-03-20 12:59:07

标签: java regex bash sed

我目前正在处理一些遗留代码(java项目),并且许多变量(15k)的第一个字符都带有下划线,例如:

_iAmAInt //should be iAmInt

(所有要替换的变量均以_开头,后跟小写字母)

所以我想我会尝试使用带有sed和regex的小脚本来清理它,到目前为止,这是我所拥有的:

while IFS= read -r -d '' file; do
   if [[ $file == *.java ]]; then 

        sed -i -E 's/([_])([a-z])/\2/g' $file

    fi  
done < <(find "$1" -type f -print0)

问题是在某些情况下,我有一些字符串(例如查询),其内容如下:"select house_id from houses"

我当前的正则表达式没有考虑到这一点,但是显然我需要以某种方式指定不要删除“”之间的_。

从我所读的书中,我可以使用负向超前Regex: match everything but specific pattern

但是我不确定这是否可以完全解决我的问题,即使整个过程是一个好主意?

欢迎任何提示或反馈,关于如何进行以及做什么或不做什么! 谢谢

编辑:是的,代码是Java,并且SonarQube将此标记为问题(尽管这不是很关键)

编辑2:感谢您提供所有答案和评论,我学到了很多东西,我会尝试一下,确保选择一个作为有效答案!

3 个答案:

答案 0 :(得分:2)

> sed -E 's/("([^"\\]|\\.)*")|_([a-z0-9]+)|([a-z][a-z0-9_]+)/\1\3\4/g'
foo _bar foo_bar " \" _zoo \" "
foo bar foo_bar " \" _zoo \" "

第一组捕获字符串文字,第三组捕获以下划线开头但不带下划线的标识符,第四组捕获所有其他标识符。第四组需要避免在标识符中间删除下划线。

答案 1 :(得分:1)

尽管我在评论中指出,sed的正则表达式对于这项工作来说有点缺乏,但我意识到sed仍然可以做到此事而没有太多的困惑。诀窍是首先保护要保留的下划线,然后删除下划线,然后还原受保护的下划线。如果可以的话,可以使用一种有机化学方法来解决这个问题。

为此,您可以依靠以下事实:除非使用sed命令,否则sed的模式空间中将永远不会有一个字符 :换行符。 sed在输入上剥离它们,(通常)在输出上发出新的,但是如果它们确实出现在模式空间中,那么它们就不是特别的了。所以考虑一下:

sed -i -e 's/([^ \t])_/\1\n/g; s/_([a-z])/\1/g; s/\n/_/g' "$file"

执行了三个替换:

  1. 每个紧跟空格或制表符的下划线都用换行符代替;
  2. (原始正则表达式的一种变体:)删除每个下划线和小写拉丁字母;和
  3. 每个换行符都用下划线代替。

再次记住,sed在输入上去除换行符,并在普通输出上追加新行,因此(3)中唯一可替换的换行符是(1)中引入的那些用于隐藏下划线的换行符想要保护免受(2)中的替换。

答案 2 :(得分:0)

请注意,您可能有一个变量,例如_return,在其中删除_会导致一个关键字。

此操作可以使用perl轻松完成,因为PCRE比sed正则表达式具有更多功能。

示例

要grep,只需显示匹配项即可。

# where ... are find options e.g. `-name '*.java'`
find "$1" -type f ... -exec perl -ne 'print "$ARGV:$_" if /"(?:\\.|[^"])*"(*SKIP)(?!)|\b_[a-z]/' {} +

更改文件:({-ised -i.bak一样,默认情况下在perl中将原始文件移动到.bak

find "$1" -type f ... -exec perl -i -pe 's/"(?:\\.|[^"])*"(*SKIP)(?!)|\b_(?=[a-z])//g' {} +

还原:替换为.bak个文件

find "$1" -type f ... -name '*.bak' -exec bash -c 'for f; do mv "$f" "${f%.bak}"; done' bash {} +

删除.bak文件

find "$1" -type f ... -name '*.bak' -delete

正则表达式的工作原理

  • "(?:\\.|[^"])*":匹配可能包含\"序列的字符串文字“ ..”
  • (*SKIP)(?!)|:回溯关键字以放弃此匹配项:
    • (*SKIP)防止在匹配字符串中当前位置之前回溯
    • (?!)匹配失败
    • |尝试与以下模式匹配
  • \b_(?=[a-z]):匹配_,其后跟单词边界(作为单词字符,后跟非单词字符),再跟小写字母([a-z]