I have the following awk code:
ip addr | grep -v '1: lo:' | grep -v '127.0.0.1' | awk '/^[0-9]+:/ {sub(/:/,"",$2); iface=$2 } /^[[:space:]]*link\/ether / {mac=$2} /^[[:space:]]*inet / {split($2, if_arr, "/"); print iface "," if_arr[1] "," mac}'
It outputs like this:
eth0,10.53.55.22,00:51:56:9g:2f:e2
But I need output like this (in double quotes):
"eth0","10.53.55.22","00:51:56:9g:2f:e2"
Just set/use OFS and you don't need to use grep if you're already using awk:
ip addr |
awk -v OFS='","' '/1: lo:|127.0.0.1/{next} /^[0-9]+:/... print "\"" iface, if_arr[1], mac "\""}'
You should probably be escaping each . in 127.0.0.1 though, whatever tool you use.
Change the print statement from
print iface "," if_arr[1] "," mac
to
print "\"" iface "\",\"" if_arr[1] "\",\"" mac "\""
Related
I am trying to extract bin names from from Cargo.toml using Bash, I enabled perl regular expression like this
First attempt
grep -Pzo '(?<=(^\[\[bin\]\]))\s*name\s*=\s*"(.*)"' ./Cargo.toml
The regular expression is tested at regex101
But got nothing
the Pzo options usage can be found here
Second attempt
grep -P (?<=(^[[bin]]))\n*\sname\s=\s*"(.*)" ./Cargo.toml
Still nothing
grep -Pzo '(?<=(^\[\[bin\]\]))\s*name\s*=\s*"(.*)"' ./Cargo.toml
Cargo.toml
[[bin]]
name = "acme1"
path = "bin/acme1.rs"
[[bin]]
name = "acme2"
path = "src/acme1.rs"
grep:
grep -A1 '^\[\[bin\]\]$' |
grep -Po '(?<=^name = ")[^"]*(?=".*)'
or if you can use awk, this is more robust
awk '
$1 ~ /^\[\[?[[:alnum:]]*\]\]?$/{
if ($1=="[[bin]]" || $1=="[bin]") {bin=1}
else {bin=0}
}
bin==1 &&
sub(/^[[:space:]]*name[[:space:]]*=[[:space:]]*/, "") {
sub(/^"/, ""); sub(/".*$/, "")
print
}' cargo.toml
Example:
$ cat cargo.toml
[[bin]]
name = "acme1"
path = "bin/acme1.rs"
[bin]
name="acme2"
[[foo]]
name = "nobin"
[bin]
not_name = "hello"
name="acme3"
path = "src/acme3.rs"
[[bin]]
path = "bin/acme4.rs"
name = "acme4" # a comment
$ sh solution
acme1
acme2
acme3
acme4
Obviously, these are no substitute for a real toml parser.
With your shown samples and attempts, please try following code with tac + awk combination, which will be easier to maintain and does the job with easiness, which will be difficult in grep.
tac Input_file |
awk '
/^name =/{
gsub(/"/,"",$NF)
value=$NF
next
}
/^path[[:space:]]+=[[:space:]]+"bin\//{
print value
value=""
}
' |
tac
Explanation: Adding detailed explanation for above code.
tac Input_file | ##Using tac command on Input_file to print it in bottom to top order.
awk ' ##passing tac output to awk as standard input.
/^name =/{ ##Checking if line starts from name = then do following.
gsub(/"/,"",$NF) ##Globally substituting " with NULL in last field.
value=$NF ##Setting value to last field value here.
next ##next will skip all further statements from here.
}
/^path[[:space:]]+=[[:space:]]+"bin\//{ ##Checking if line starts from path followed by space = followed by spaces followed by "bin/ here.
print value ##printing value here.
value="" ##Nullifying value here.
}
' | ##Passing awk program output as input to tac here.
tac ##Printing values in their actual order.
e.g.
Find line "1437421130",""
but not "1437421130","92729392"
Cant figure out how to handle double quotes. ( I am an idiot when it comes to grep )
I tried
echo "1437421130","" | grep '"\d{10}",""'
echo "1437421130","" | grep '"[0-9]{10}",""'
Did this on centos. Used single quotes to avoid the double quote escaping. -E to allow the {10}
New to scripting. I have only one line & one file. How do I capture summerfruit value (ie "mango") & pass it to another variable from the below line.
.. abc.dfe summer.fruit=mango summer.vegetable=potato projects.blah ...
If your grep supports Perl-compatible regular expressions (PCRE):
summerfruit=$(grep -Po 'summer\.fruit=\K[^ ]+' file)
The \K doesn't print the matched summer.fruit= and [^ ]+ matches one or more non-space characters after the =.
without PCRE:
summerfruit=$(grep -o 'summer\.fruit=[^ ]*' file | grep -o '[^=]*$')
With sed:
summerfruit=$(sed 's/.*summer\.fruit=\([^ ]*\).*/\1/' file)
With awk:
summerfruit=$(awk '{
for (i=1;i<=NF;i++)
if ($i ~ /^summer\.fruit=/){ sub(/^[^=]*=/,"",$i); print $i; exit }
}' file)
I've placed my PATH in a text file and would like to print each path on a newline using a simple command in UNIX.
I've found a long way to do it that goes like this...
cat Path.txt | awk -F\; '{print $1"\n", $2"\n", ... }'
This however seems inefficient so I know there must be a way to quickly print out my results on new lines each time without having to manually call each field separated by the delimiter.
Yet another way:
echo $PATH | tr : '\n'
or:
tr : '\n' <Path.txt
The tr solution is the right one but if you were going to use awk then there'd be no need for a loop:
$ echo "$PATH"
/usr/local/bin:/usr/bin:/cygdrive/c/winnt/system32:/cygdrive/c/winnt
$ echo "$PATH" | awk -F: -v OFS="\n" '$1=$1'
/usr/local/bin
/usr/bin
/cygdrive/c/winnt/system32
/cygdrive/c/winnt
I have a Perl script that I use for this:
#!/usr/bin/env perl
#
# "#(#)$Id: echopath.pl,v 1.8 2011/08/22 22:15:53 jleffler Exp $"
#
# Print the components of a PATH variable one per line.
# If there are no colons in the arguments, assume that they are
# the names of environment variables.
use strict;
use warnings;
#ARGV = $ENV{PATH} unless #ARGV;
foreach my $arg (#ARGV)
{
my $var = $arg;
$var = $ENV{$arg} if $arg =~ /^[A-Za-z_][A-Za-z_0-9]*$/;
$var = $arg unless $var;
my #lst = split /:/, $var;
foreach my $val (#lst)
{
print "$val\n";
}
}
I invoke it like:
echopath $PATH
echopath PATH
echopath LD_LIBRARY_PATH
echopath CDPATH
echopath MANPATH
echopath $CLASSPATH
etc. You can specify the variable name, or the value of the variable; it works both ways.
With Perl for UNIX/UNIX-likes :
echo $PATH | perl -F: -ane '{print join "\n", #F}'
With any OSes (tested on Windows XP, Linux, Minix, Solaris):
my $sep;
my $path;
if ($^O =~ /^MS/) {
$sep = ";";
$path = "Path";
}
else {
$sep = ":";
$path = "PATH";
}
print join "\n", split $sep, $ENV{$path} . "\n";
If using bash for Unix, try the following code :
printf '%s\n' ${PATH//:/ }
This use bash parameter expansion
awk:
echo $PATH|awk -F: '{gsub(/:/,"\n");print}'
perl:
echo $PATH|perl -F: -lane 'foreach(#F){print $_}'
for AWK, in addition to:
echo $PATH | awk -vFS=':' -vOFS='\n' '$1=$1'
You can:
echo $PATH | awk -vRS=':' '1'
I have some code which has Windows path separator hard-coded all over it.
blah + '\\' + blah
I've been trying to find them with
grep -FR "\\\\" *.py
grep -ER "^(.+?)\\\\" *.py
which are obvious failures. What should the expression be?
grep -FR '\\' *.py
does work in my environment (tested)
The -F indicates fixed string, and only 2 slashes are needed to match 2 slashes in your file.
I hope this helps.
\ is the escape character, so to get a \, you use \\, and to get \\, you use \\\\
foo#bar: ~ > cat test
blah + '\\' + blah
foo#bar: ~ > grep '\\\\' test
blah + '\\' + blah
try
grep '\\\\' *.py
if you want to grab 2 slashes