从代码行中删除变量名(JS 中的伪代码)

Posted

技术标签:

【中文标题】从代码行中删除变量名(JS 中的伪代码)【英文标题】:Removing Variable Names From Line Of Code (Psuedocode in JS) 【发布时间】:2021-06-02 17:01:39 【问题描述】:

我用一些正则表达式编写了一个脚本来进行元编程。但是,我发现我无法使用一些较新的正则表达式功能,例如负后视,并且由于我在该机器上的限制,我无法安装 Perl 或其他可能的解决方案来获得访问权限。因此,我正在寻找一个 bash 脚本来完成从文本字符串中删除某些单词,而该字符串恰好是从 C++ 文件中提取的。

这是我得到的文本输入示例,它看起来像 C++ 函数签名:

int test(int aaaa, Vector<int, bool*> bbbb, Bar**cccc, Foo, Transform&eeee)

我想删除代表变量名称的字符串。在此示例中,即:aaaabbbbcccceeee

输出应该是这样的,就好像它只是一个前向声明:

int test(int, Vector<int, bool*>, Bar**, Foo, Transform&)

我的解决方案是做一些事情,但我不确定是否有更好的 bash 解决方案来满足我的需求-结束。

我用 JS 编写了这个脚本来帮助完成我想要的。希望对你有帮助!

var text = 'int test(int aaaa, Vector<int, bool*> bbbb, Bar**cccc, Foo, Transform&eeee)'
var index = 0
var insideparentheses = false
var deleting = false
var readdatatype = false
var insidebrackets = 0
while(index < text.length) 
    if(text[index] == '(') 
        insideparentheses = true
        deleting = false
        readdatatype = false
        readletter = false
    
    if(text[index] == ')') 
        insideparentheses = false
        deleting = false
        readdatatype = false
        readletter = false
    
    if(text[index] == '<') 
        insidebrackets++
    
    if(text[index] == '>') 
        insidebrackets--
        readletter = true
    
    if(insideparentheses && insidebrackets == 0) 
        if(text[index].match(/[a-zA-Z]/gi) != null) 
            readletter = true
        
        if(text[index] == '*') 
            readdatatype = true
        
        if(text[index] == '&') 
            readdatatype = true
        
        if(text[index] == ' ') 
            if(readletter) 
                readdatatype = true
             else 
                readdatatype = false
            
        
        if(text[index] == ',') 
            deleting = false
            readdatatype = false
            readletter = false
        
        if(text[index].match(/[_ a-zA-Z]/gi) != null) 
            if(readdatatype) 
                deleting = true
             else 
                deleting = false
            
        
        if(deleting) 
            text = text.substring(0, index) + text.substring(index + 1)
         else 
            index++
            continue
        
     else 
        index++
        continue
    

console.log(text)

编辑:变量可以命名为任何在 C++ 中有效的名称,例如 [_a-zA-Z]+,而不仅仅是同一个字母的 4 个,重复 4 次...:P

【问题讨论】:

我确信这可以在sed 中完成,但我也确信这将是相当可怕的。是否可以接受 awk 解决方案? 嗨。我对正则表达式非常满意,sed 不适用于我的解决方案,因为我的平台上没有像lookbehind 这样的正则表达式功能。如果您想出一个不使用后向/前瞻的sed 解决方案,我可以尝试一下!此外,awk 无法安装,这是我肯定已经尝试过的。 :P Perl 怎么样? @tripleee,在问题中,我指定我无法在环境中安装 Perl 作为解决此问题的方法。 哦,对不起,我错过了。您可能可以做一些逻辑将整行划分为保持空间和模式空间,然后处理模式空间,然后将它们合并在一起;但这些解决方案往往是只写的,特别是如果您对sed 概念不是很熟悉。参见例如一些potong's answers 用于演示此类解决方案的外观。 【参考方案1】:

使用正则表达式而不是专门的工具来解析这些东西是 会很脆弱,因为它可能会在额外的空白处失败,例如。

不过,这里有一个使用 POSIX 的 sed 版本 ERE 正则表达式, 假设输入有效且简单。 如果您的sed 不理解\n(GNU sed 可以)尝试 用反斜杠换行符替换它。

sed -E -e '
:S
s/^(([^<]*<[^>]*>)*[^<]*), */\1\n/
tS
s/(\n|\()([[:alpha:]_][[:alnum:]_]*)(\n|\)$)/\1\2 ident\3/g
s/([[:print:]])([ ]*[[:alpha:]_][[:alnum:]_]*)(\n|\)$)/\1\3/g
s/[ ]*\n/, /g
' -- data

地点:

第一个s:用&lt; &gt; 替换最后一个(* 是贪婪的)逗号 换行符 t:如果进行了替换,则循环返回,以使每行一个参数 第二个s:如果参数中没有标识符,则插入一个以简化以下替换(第三个s) 第三个s:剥离标识符; “打印”LC_CTYPE 定义为“alnum”、“punct”和空格 4th s:将所有行合并为一个

测试数据:

int test(int aaaa, Vector<int, bool*> bbbb, Bar**cccc, Foo, Transform&eeee)
long tst2(Vector<bool*, str*> vbs, int i, Quux<Foo, int*>, Bar*bp)
longlong tst3(long l, Foo f, Vector<int, bool*, str*> vibs, Vector<int>vi, Bar**bpp, Phoo&)
int (*ff(int))(int*, int)
int (*pfc)(const char* p1, const char* p2)

输出:

int test(int, Vector<int, bool*>, Bar**, Foo, Transform&)
long tst2(Vector<bool*, str*>, int, Quux<Foo, int*>, Bar*)
longlong tst3(long, Foo, Vector<int, bool*, str*>, Vector<int>, Bar**, Phoo&)
int (*ff(int))(int*, int)
int (*pfc)(const char*, const char*)

【讨论】:

哇!这有效,即使它没有直接回答关于转换 JS 代码的部分问题!谢谢!!好激动!! @crait:嗯,您的帖子包含一个sed 标签,我对此进行了回复。如果您更喜欢其他工具,也许我的正则表达式中的想法会很有用。【参考方案2】:

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

sed 's/ \?\([abcde]\)\1\1\1//g' file

在整个文件中全局删除一个可选空格,后跟aaaabbbbccccddddeeee


编辑:

sed -E 's/\((.*)\)/(\n\1\n)/;T;h;s/.*\n(.*)\n.*/\1/;y/,/\n/
        s#.*#echo "&"|sed -E "s/^ +//;s/( |(\\*\\*|\\\&))\\S+$/\\2/"#e
        s/\n/, /g;H;g;s/\n.*\n(.*)\n(.*)/\2\1/' file

将线分成三部分。

在中间部分运行单独的 sed 调用。

将零件重新组合在一起。

这可能无法满足所有可能性(OP 将需要改进上述解决方案),但应该是一个开始。

注意最好利用原始语言的自省来解决这样的问题。

【讨论】:

这不是答案。变量名称为aaaaabbbbb 等都是示例,我认为我的问题很清楚。变量可以命名为任何字母数字,就像在 C++ 中一样。如果数据类型使用该模式,这也会失败,例如void whatever(aaaaa foo, int bar)

以上是关于从代码行中删除变量名(JS 中的伪代码)的主要内容,如果未能解决你的问题,请参考以下文章

Python3基础 类的伪私有属性 __加变量名 的示例

PHP中的变量

shell变量替换

JS中变量名和函数名重名

小白之旅18

shell-变量