Print a specific part in an output
Let us suppose that there is a command such as:
cat /boot/config-3.19.0-32-generic | grep CONFIG_ARCH_DEFCONFIG
The output is as such:
CONFIG_ARCH_DEFCONFIG="arch/x86/configs/x86_64_defconfig"
Now, my question is: Are there any commands which will only print what is inside the inverted commas, i.e., " "
?
And could you please explain the command a little? Thank you! in advance.
Yes, you can do that. Your command would be:
cat /boot/config-3.19.0-32-generic | grep CONFIG_ARCH_DEFCONFIG | awk -F'"' '{print $2}'
which would return only:
arch/x86/configs/x86_64_defconfig
The awk
command uses field separators with the -F
command, and to set it to use double-quotes, you type it in with single-quotes around it like -F'"'
. Then the '{print $2}'
tells awk to print the second set after the field separator.
Hope this helps!
You can do that with a single grep
command:
grep -Po '^CONFIG_ARCH_DEFCONFIG="\K[^"]*' /boot/config-3.19.0-32-generic
Or (a bit longer and more convulted):
grep -Po '^CONFIG_ARCH_DEFCONFIG="\K.*?(?=")' /boot/config-3.19.0-32-generic
-
-P
: tellsgrep
to interpret the pattern as a PCRE (Perl Compatible Regular Expression); -
-o
: tellsgrep
to print only the match; -
^CONFIG_ARCH_DEFCONFIG="
: matches aCONFIG_ARCH_DEFCONFIG="
string at the start of the line; -
\K
: discards the previously matched substring;
#1:
-
[^"]*
: matches any number of any character not"
(greedily).
#2:
-
.*?
: matches any number of any character (lazily); -
(?=")
: lookahead (zero-lenght assertion, it doesn't match any character); matches if the following character is a"
.
% grep -Po '^CONFIG_ARCH_DEFCONFIG="\K[^"]*' /boot/config-4.2.0-16-generic
arch/x86/configs/x86_64_defconfig
% grep -Po '^CONFIG_ARCH_DEFCONFIG="\K.*?(?=")' /boot/config-4.2.0-16-generic
arch/x86/configs/x86_64_defconfig
There are many ways to skin this cat, here is a sed
way:
sed -nr 's/^CONFIG_ARCH_DEFCONFIG="([^"]+)"$/\1/p' /boot/config-3.19.0-32-generic
Here we are matching the line and capturing the desired portion i.e. the portion within double quotes (([^"]+)
) and then replacing the whole line with the captured group (\1
) only.
Example:
% sed -nr 's/^CONFIG_ARCH_DEFCONFIG="([^"]+)"$/\1/p' /boot/config-3.13.0-32-generic
arch/x86/configs/x86_64_defconfig
What, no perl
?
grep CONFIG_ARCH_DEFCONFIG /boot/config-3.19.0-32-generic |
perl -pe 's/.*?"([^"]*).*/$1/'
The perl
will -p
rint every line after applying the script given by -e
. The s/foo/bar/
will substitute foo
with bar
. Patterns in parentheses are "captured" and can be referred to as $1
, $2
... $N
where $1
is the 1st pattern captured, $2
the second etc. The regular expression will look for everything until the first quote (.*?"
), then capture 0 or more non-"
characters ([^"]*
) and then everything else. The whole thing is replaced with the captured pattern.
You can also leave the pattern matching to perl
:
perl -ne 's/.*CONFIG_ARCH_DEFCONFIG="([^"]*).*/$1/ && print' /boot/config-3.19.0-32-generic
Here is a combination of grep
and cut
, that does the same job.
$ grep "CONFIG_ARCH_DEFCONFIG" /boot/config-3.19.0-32-generic | cut -d"\"" -f2
arch/x86/configs/x86_64_defconfig
Explanation:
-
grep "CONFIG_ARCH_DEFCONFIG" /boot/config-3.19.0-32-generic
is the part that finds the line, in the standard grep syntax:grep [OPTIONS] PATTERN [FILE...]
. The output goes through pipe to the next stage -
cut -d"\"" -f2
. This part uses cut to crop-off text separated by specific delimiter (which is specified with-d
flag). We have to escape the double quote with backslash so that shell allows taking double quote as one of the options to thecut
command, rather than input to the shell itself. Nowcut
will treat output fromgrep
as separated by"
and split into three columns,CONFIG_ARCH_DEFCONFIG
,arch/x86/configs/x86_64_defconfig
, and empty space. The line we need is the second column, that means we need to use-f2
flag.