如何从保留转义哈希字符的文件中删除所有注释

如何从保留转义哈希字符的文件中删除所有注释

我知道以前已经问过这个问题,但这只是有点不同:我需要删除所有注释,排除转义#或不意味着开始注释(在单或双顶点之间)

从以下文本开始:

test
# comment
comment on midline # comment
escaped hash "\# this is an escaped hash"
escaped hash "\\# this is not a comment"
not a comment "# this is not a comment - double apices"
not a comment '# this is not a comment - single apices'
this is a comment \\# this is a comment
this is not a comment \# this is not a comment

我想获得

test
comment on midline
escaped hash "\# this is an escaped hash"
escaped hash "\\# this is not a comment"
not a comment "# this is not a comment - double apices"
not a comment '# this is not a comment - single apices'
this is a comment \\
this is not a comment \# this is not a comment

我试过

grep -o '^[^#]*' file

但这也会删除转义的哈希值。

注意:我正在处理的文本确实已转义#( \#) 但缺少双重转义#( \\#),因此是否保留它们对我来说并不重要。我想删除它们会更简洁,因为事实上哈希值没有被转义。

答案1

sed可以删除以 a 开头的行#(前面有零个或多个空格),并删除以#它开头的所有不跟在单个反斜杠后面的字符串(并且仅当它不在引号1之间时):

sed '/^[[:blank:]]*#/d
/["'\''].*#.*["'\'']/!{
s/\\\\#.*/\\\\/
s/\([^\]\)#.*/\1/
}' infile

1:此解决方案假设一行中有一对引号

答案2

这是一个比听起来更复杂的问题,但并没有超出正则表达式的能力。分析它:整行由非注释文本组成,后面可以选择注释文本。非注释文本中可以出现的内容:

  1. \, #, ',之外的任何字符"
  2. \后跟任意字符
  3. 带引号的字符串,以 and 开头和结尾",可能包含
    • \A) 除或以外的任何字符"
    • B)\后跟任意字符
  4. 带引号的字符串,以 and 开头和结尾',可能包含
    • '

(两种引用的处理方式不同取决于 unix shell 的处理方式 - 根据口味进行调整)

将其直接转换为正则表达式,您需要:

s/^([non comment])[comment]$/\1/
non comment = ([^\\"'#]|\\.|"([^\\"]|\\.)*"|'[^']*')*
              (11111111|222|3(AAAAAA|BBB)33|4444444)*
comment = #.*
Therefore
s/^(([^\\"'#]|\\.|"([^\\"]|\\.)*"|'[^']*')*)#.*$/\1/

对于正则表达式,您需要在、和字符sed之前添加更多反斜杠:(|)

s/^\(\([^\\"'#]\|\\.\|"\([^\\"]\|\\.\)*"\|'[^']*'\)*\)#.*$/\1/

bash 需要额外的引用:

sed 's/^\(\([^\\"'\''#]\|\\.\|"\([^\\"]\|\\.\)*"\|'\''[^'\'']*'\''\)*\)#.*$/\1/'

grep -o编辑:直到我看到@StéphaneChazelas 的回答,我才意识到存在。相同的核心正则表达式可以适应这种方法,而egrep可以让您避免执行大部分额外的反斜杠:

grep -Eo '^([^\\"'\''#]|\\.|"([^\\"]|\\.)*"|'\''[^'\'']*'\'')*'
grep -Eo "^([^\\\\\"'#]|\\\\.|\"([^\\\\\"]|\\\\.)*\"|'[^']*')*"

这两个在含义上是相同的(并且偶然是相同的长度),只是 shell 引用的不同方法 - 我个人更喜欢第一种方法,因为单引号是我唯一需要担心的字符,但你可能会发现第二种方法更具可读性,并且它与您用其他编程语言编写的内容非常相似。

需要注意的是,正则表达式不知道如何处理包含不匹配引号的行。它们根本不匹配正则表达式,因此 sed 命令不会删除任何内容,而 grep 命令将删除所有内容。

答案3

这个命令应该可以工作。

sed -e '/^#/d;s/[^\/]#.*$//' <file-path>

相关内容