我知道以前已经问过这个问题,但这只是有点不同:我需要删除所有注释,排除转义#
或不意味着开始注释(在单或双顶点之间)
从以下文本开始:
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
这是一个比听起来更复杂的问题,但并没有超出正则表达式的能力。分析它:整行由非注释文本组成,后面可以选择注释文本。非注释文本中可以出现的内容:
- 除
\
,#
,'
,之外的任何字符"
\
后跟任意字符- 带引号的字符串,以 and 开头和结尾
"
,可能包含\
A) 除或以外的任何字符"
- B)
\
后跟任意字符
- 带引号的字符串,以 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>