我读过很多关于如何删除以特定字符或字符集开头的行的 sed 示例,这并不具有挑战性,但我似乎无法破解这个示例。我想删除文件中以字母“i”开头且不以“.conf”结尾的所有行。
以下是列表示例:
include /usr/local/choops/users/2488.conf
include /usr/local/cho
include /usr/local/choops/users/2492.conf
i
incl
上例中需要删除的 3 行是:
include /usr/local/cho
i
incl
它们是不完整的,不能在那里。
我尝试了在 StackExchange 和 StackOverflow 以及其他各种论坛上看到的示例的一些变体,但我似乎无法做到正确。这是我尝试过的:
sed -i '/^i.*[^\.conf]$/d' /usr/local/choops/users/main.conf
sed -i '/^i.\*\[^\\.conf\]$/d' /usr/local/choops/users/main.conf
sed -i '/^i.*[^.conf]$/d' /usr/local/choops/users/main.conf
其中 main.conf 是列出一组 .conf 文件的文件,如上所示。我认为这个不会太复杂,但这些命令似乎都不适合我。我根据各种来源和对 sed 的理解构建了命令。任何帮助将不胜感激,我很困惑。
以下内容与我想要的相反,但我想这很简单:
sed -i 's/i.*.conf//' main.conf
答案1
有两个子句必须同时满足(“以 i 开头”、“不以 .conf 结尾”)。对于要从输出中排除的行,需要单独测试每个子句,然后将其与在一起。
输入示例(添加了不以“i”开头的额外行):
$ cat input.txt
include /usr/local/choops/users/2488.conf
this line doesn't begin with i
include /usr/local/cho
this line doesn't begin with i but does end in .conf
include /usr/local/choops/users/2492.conf
i
incl
和perl
:
$ perl -ne 'print unless (/^i/ && ! /\.conf$/)' input.txt
include /usr/local/choops/users/2488.conf
this line doesn't begin with i
this line doesn't begin with i but does end in .conf
include /usr/local/choops/users/2492.conf
和sed
:
$ sed -ne '/^i/ {/\.conf$/!d;};p' input.txt
include /usr/local/choops/users/2488.conf
this line doesn't begin with i
this line doesn't begin with i but does end in .conf
include /usr/local/choops/users/2492.conf
或者(可能更好),正如 @seshoumara 建议的那样:
sed -e '/^i/ {/\.conf$/!d;}' input.txt
所有三个版本都从输出中删除不需要的行,打印其他所有内容。
答案2
看来你有两个条件,如果行以“i”开头,如果行不以“.conf”结尾,则为 true。不要进行一次搜索,而是分两次进行。
sed -i '/^i/{/\.conf$/!d}' /usr/local/choops/users/main.conf
或者,如果你有相反的事情,就否定它。
sed -i '/^i.*\.conf$/!d' /usr/local/choops/users/main.conf
请注意,点需要转义,否则它是一个表示任何字符的正则表达式。
您尝试的“[^abc]”正则表达式实际上表示:不是“a”、“b”或“c”的单个字符。可能是“j”或“z”。无论该正则表达式匹配什么,它仍然是单个字符。最后,“[]”或“[^]”中的字符不能具有任何正则表达式含义,而只是文字字符列表,因此“.”总是意味着点,不需要转义它。但在 // 或 s/// 中,您希望根据您的情况将其转义。
答案3
我想删除文件中以字母“i”开头且不以“.conf”结尾的所有行
- 让我们
A
表示“以字母开头i
” - 让我们
B
表示“结束于.conf
”
使用布尔逻辑我们可以说你想要删除匹配条件“A and not B”的行:
A . B'
此外,我们可以将其重写为“{ not A, or B } 的否定”:
( A' + B'' )' = ( A' + B )'
使用grep
我们可以将其反转为保持(而不是删除)与表达式匹配的行,因此:
( A' + B )
在代码中这将变成,
grep -E '^[^i]|\.conf$'
尽管实际上我们还需要考虑根本不以任何字符开头的行(即它们是空白的),
grep -E '^[^i]|\.conf$|^$'
使用示例文件,您可以保留这些行:
include /usr/local/choops/users/2488.conf
include /usr/local/choops/users/2492.conf
通常的规则适用于就地编辑(这是烟雾和镜子),所以我们自己应用它
grep ... file >file.tmp &&
mv -f -- file.tmp file
rm -f -- file.tmp
答案4
begin with the letter "i" and DO NOT end with ".conf"
使用任何 awk,我们只需将您指定的匹配要求转换为代码即可识别您要删除的行:
$ awk '/^i/ && !/\.conf$/' file
include /usr/local/cho
i
incl
然后简单地否定该条件以获得您想要保留的行:
$ awk '!(/^i/ && !/\.conf$/)' file
include /usr/local/choops/users/2488.conf
include /usr/local/choops/users/2492.conf
如果您愿意,可以缩写为德摩根定律到:
$ awk '!/^i/ || /\.conf$/' file
include /usr/local/choops/users/2488.conf
include /usr/local/choops/users/2492.conf