2

对于文件列表,我想匹配那些不以.txt. 我目前正在使用这个表达式:

.*(txt$)|(html\.txt$)

此表达式将匹配以 结尾的所有内容.txt,但我希望它做相反的事情。


应该匹配:

happiness.html
joy.png
fear.src

应该匹配:

madness.html.txt
excitement.txt

我想得到这个,所以我可以将它与fswatch配对使用:

fswatch -0 -e 'regex here' . | xargs -0 -n 1 -I {} echo "{} has been changed"

问题是它似乎不起作用。

PS:我使用标签 bash 而不是 fswatch 因为我没有足够的声望点来创建它。对不起!

4

4 回答 4

3

尝试使用lookbehind,如下所示:

.*$(?<!\.txt)

示范

基本上,这匹配任何文本行,只要最后 4 个字符不是".txt".

于 2014-10-28T19:34:00.457 回答
3

为此,您可以使用 Negative Lookahead。

^(?!.*\.txt).+$

现场演示

您可以使用选项将此表达式与 grep 一起使用-P

grep -Po '^(?!.*\.txt).+$' file
于 2014-10-28T19:34:47.597 回答
1

由于问题已标记为bash,因此可能不支持前瞻(除了grep -P),这是一种grep不需要前瞻的解决方案:

grep -v '\.txt$' file
happiness.html
joy.png
fear.src

编辑:您可以使用此xargs命令来避免匹配*.txt文件:

xargs -0 -n 1 -I {} bash -c '[[ "{}" == *".txt" ]] && echo "{} has been changed"'
于 2014-10-28T19:39:32.580 回答
0

这真的取决于您使用的是什么正则表达式工具。许多工具提供了一种反转正则表达式含义的方法。例如:

重击

# succeeds if filename ends with .txt
[[ $filename =~ "."txt$ ]]
# succeeds if filename does not end with .txt
! [[ $filename =~ "."txt$ ]]
# another way of writing the negative
[[ ! $filename =~ "."txt$ ]]

grep

# succeeds if filename ends with .txt
egrep -q "\.txt$" <<<"$filename"
# succeeds if filename does not end with .txt
egrep -qv "\.txt$" <<<"$filename"

awk

/\.txt$/ { print "line ends with .txt" }
! /\.txt$/ { print "line doesn't end with .txt" }
$1 ~ /\.txt$/ { print "first field ends with .txt" }
$1 !~ /\.txt$/ { print "first field doesn't end with .txt" }

对于喜欢冒险的人,可以在任何兼容 posix 的正则表达式引擎中工作的 posix ERE

/[^t]$|[^x]t$|[^t]xt$|[^.]txt$/

于 2014-10-28T19:49:39.450 回答