Bash:删除双斜线(取消注释行)

时间:2015-04-21 15:39:18

标签: string bash shell

我想删除行开头的双斜杠以取消注释一行代码,例如第一个注释。我的方法适用于很多其他情况,但这次还不够。这是我的文件.sh:

中的一段代码
while read line
    do
        if [[ $line == *"#define asdasd"* ]]
        then
            local prefix="\\/\\/ "
            local new=${line#$prefix}
            local sub="s/$line/$new/g"
            echo "old line: " $line
            echo "new line: " $new
            echo $sub
            perl -pi -e "$sub" $FILE
            exit
           fi
    done < $FILE

编辑:

我的问题比这段代码更复杂。我想取消注释(删除双斜线)只有一行匹配模式的行,而不一定是第一行。这就是为什么我无法对整个文件进行操作,而是逐行操作的原因。因此,所有“perl on match”解决方案在我的案例中都不起作用。

编辑:

我正按照一些用户的建议编辑我的问题。

  • 背景:我正在使用嵌入式(复杂)操作系统,我无法为自己的目的修改每个文件(即makefile)。
  • 目的:我想多次构建代码,每次都启用不同的标志。

在我当前的解决方案中,我收集了头文件中的所有标志,并且我在每次构建时只能逐个启用。这是我的.h文件的一个例子:

#ifndef SYSTEM_H
#define SYSTEM_H

#include <...>

#define BLA       1
#define BLABLA    2
#define BLABLABLA 3

// #define OPT_0 // Options disabled
// #define OPT_1
#define OPT_2 // Option enabled
// #define OPT_...
// #define OPT_...
// #define OPT_N

[...]

#define function(__exp) \
  [...]

#endif

正如您所看到的,我不知道启用/禁用了多少选项,还有其他#define指令。

我正在编写一个脚本,一次启用一个标志并构建项目。每次重命名编译的文件以防止覆盖。我的一个解决方案是基于上面列出的代码,但不幸的是perl指令不会修改.h文件,删除所选行开头的双斜杠。

3 个答案:

答案 0 :(得分:3)

Fedorqui's comment是正确的,但你正在做出真正的一餐!

要编辑您感兴趣的行,只需使用Perl:

perl -pi -e 's/^\/\/// if /#define asdasd/' "$FILE"

这将读取您的文件并进行替换以从匹配模式/#define asdasd/的行的开头删除斜杠。

在这种情况下并不短,但你也可以将这两种模式结合起来,如下所示:

perl -pi -e 's/^\/\/(.*#define asdasd)/\1/' "$FILE"

目前还不清楚是否要求只执行一次替换,但如果是,则可以将命令更改为:

perl -pi -e 's/^\/\/// if /#define asdasd/ && !$n++' "$FILE"

!$n++仅在第一次评估时才为真,因此只会进行一次替换。

答案 1 :(得分:1)

如果您确实需要逐行处理文件 ,那么如何解决读取和写入<的问题循环中的em>相同文件 ,由@fedorqui在评论中指出(代码使用bash语法):

while IFS= read -r line; do
  if [[ $line == *"#define asdasd"* ]]
  then
    # ... process "$line" and update "$FILE"
  fi
done <<<"$(< "$FILE")"
  • "$(< $FILE)"预先读取整个文件 ,然后使用here-string将其传输到while循环的标准输入。
    • 由于一次性读取整个文件,因此不建议使用此方法来处理大量输入文件。
    • 旁注:最好不要使用全大写变量名,例如$FILE,以防止与环境/特殊shell变量发生冲突。
  • 另请注意,我已使read命令更健壮:IFS=表示保留了前导和尾随空格(您可能想要也可能不想要),{{1}确保-r个实例不被“吃掉”#34; \

至于循环中的代码

  • readnew=${line#$prefix} 的开头 剥离//,因为您已经< em>转义 $line个字符。分配到/ - 改为使用$prefix。请注意, prefix='//'/ 中任何未转义的$line都会破坏您的$new命令 - 其他字符。也可能导致问题:见下一点。

  • perl是构建替换命令的脆弱方式,因为如果sub="s/$line/$new/g"和/或$line碰巧包含字符在正则表达式和替换字符串的上下文中具有特殊含义,或者甚至只是分隔符字符串$new,该命令将行为异常或中断

  • 您可以执行安全转义字符串,以便在/ perl中使用以下 s///函数(解释为here]:
bash
# SYNOPSIS
#   quotePerlRe <text>
quotePerlRe() { sed -e 's/[^^\\$]/[&]/g; s/\^/\\^/g; s/\\/\\\\/g; s/\$/\\$/g; $!a\'$'\n''\\n' <<<"$1" | tr -d '\n'; }

然后您将按如下方式调用它们:

# SYNOPSIS
#  quotePerlSubst <text>
quotePerlSubst() {
  IFS= read -d '' -r < <(sed -e ':a' -e '$!{N;ba' -e '}' -e 's/[$/\]/\\&/g; s/\n/\\&/g' <<<"$1")
  printf %s "${REPLY%$'\n'}"
}

答案 2 :(得分:0)

你可以像这样使用sed吗

sed -i -e '/#define asdasd/ s,^//,,' $FILE

所以你只会匹配你想要的模式,然后删除双斜杠。