4

I want to find all packages which provide a shared object containing "ssl" in the file name. The apt-file manpage says:

--regexp | -x Treat pattern as a (perl) regular expression. See perlreref(1) for details. Without this option, pattern is treated as a literal string to search for.

Therefore my first try was

apt-file search --regexp .*ssl.*\.so.*

This, however, gave me results such as

witty-examples: /usr/lib/Wt/examples/feature/client-ssl-auth/resources

which has no ".so" in the file name.

I played around a bit and came up with

apt-file search --regexp .*ssl.*\\.so.*

i.e. I escaped the backslash which was supposed to escape the dot. This gave me the results I wanted.

Could someone explain why I need a double backslash in this case?

3 Answers3

5

You need a double backslash \\ because the single backslash is not only the regex escape character but also the one your shell uses. E.g. you escape the dot, which on shell level just interprets to a regular dot, that is then passed to apt-get and machtes every character (as a regular dot usually does).

So the answer is, first the string is interpreted by the shell, where the backslash has one meaning, and after that, it is passed to apt-get. The regex-engine of apt-get then interpretes the preprocessed string again. There the backslash has been replaced (and also has a slightly different meaning).

Another solution is to put the regex in quotes as in:

apt-file search --regexp '.*ssl.*\.so.*'
con-f-use
  • 19,041
3

The problem is that as you are using no quoting, you need to escape both the shell and the regular expression interpreter both to interpret . as literal.

That's the reason why quoting is important. Your first pattern would work if you just use quotes around it :

apt-file search --regexp '.*ssl.*\.so.*'

The main thing to note that our final goal is to let the regex interpreter of apt-file to take the . literally rather than in the usual manner i.e. any single character.

The second case :

apt-file search --regexp .*ssl.*\\.so.*
  • The first \ here is to escape the shell as shell treats any \ as the part of backslash escaped sequences e.g. shell treats \n as newline, \t as horizontal tab etc.

    With a single \ as in .*ssl.*\.so.*, the shell treats . as \ escaped special character but . has no special meaning to shell, so just \ is removed by shell leaving only a .. With \\. shell removes the first \ leaving behind \. as a literal \ is represented by \\ in shell.

  • So we have .*ssl.*\.so.* left as the Regex pattern to be interpreted by apt-file's Perl Regex interpreter. So you would get the desired result.

heemayl
  • 93,925
1

If you don't use a quoted pattern, you have to escape the backslash for the RegEx:

apt-file search --regexp .*ssl.*\\.so.*

With a quoted pattern, you don't need that:

apt-file search --regexp '.*ssl.*\.so.*'

Example

$ apt-file search --regexp .*ssl.*\\.so.* > ~/tmp/bar
$ apt-file search --regexp '.*ssl.*\.so.*' > ~/tmp/foo
$ diff foo bar | wc -l
0
A.B.
  • 92,125