Shell Linux : grep exact sentence with NULL charac

2019-05-23 22:32发布

问题:

I have a file like

key\0value\n
akey\0value\n
key2\0value\n

I have to create a script that take as argument a word. I have to return every lines having a key exactly the same than the argument.

I tried

grep -aF "$key\x0"

but grep seems to do not understand the \x0 (\0 same result). Futhermore, I have to check that the line begins with "$key\0"

I only can use sed grep and tr and other no maching commands

回答1:

To have the \0 taken into account try :

  grep -Pa "^key\x0"

it works for me.



回答2:

Using sed

sed will work:

$ sed -n '/^key1\x00/p' file
key1value

The use of \x00 to represent a hex character is a GNU extension to sed. Since this question is tagged linux, that is not a problem.

Since the null character does not display well, one might (or might not) want to improve the display with something like this:

$ sed -n 's/^\(akey\)\x00/\1-->/p' file
akey-->value

Using sed with keys that contain special characters

If the key itself can contain sed or shell active characters, then we must escape them first and then run sed against the input file:

#!/bin/bash
printf -v script '/^%s\\x00/p' "$(sed 's:[]\[^$.*/]:\\&:g' <<<"$1")"
sed -n "$script" file

To use this script, simply supply the key as the first argument on the command line, enclosed in single-quotes, of course, to prevent shell processing.

To see how it works, let's look at the pieces in turn:

  • sed 's:[]\[^$.*/]:\\&:g' <<<"$1"

    This puts a backslash escape in front of all sed-active characters.

  • printf -v script '/^%s\\x00/p' "$(sed 's:[]\[^$.*/]:\\&:g' <<<"$1")"

    This creates a sed command using the escaped key and stores it in the shell variable script.

  • sed -n "$script" file

    This runs sed using the shell variable script as the sed command.

Using awk

The question states that awk is not an acceptable tool. For completeness, though, here is an awk solution:

$ awk -F'\x00' -v k=key1 '$1 == k' file
key1value

Explanation:

  • -F'\x00'

    awk divides the input up into records (lines) and divides the records up into fields. Here, we set the field separator to the null character. Consequently, the first field, denoted $1, is the key.

  • -v k=key1

    This creates an awk variable, called k, and sets it to the key that we are looking for.

  • $1 == k

    This statement looks for records (lines) for which the first field matches our specified key. If a match is found, the line is printed.