pattern extraction matching pattern a OR pattern b (sed/awk) - awk

How do I extract the word after the first -n whether or not there is a blank space after?
In the example below it would return test-name on both cases. This awk code is working properly only on the first example.
$ echo "a -n test-name -bc d-e -fe -ntest" | awk 'BEGIN{FS="-n *"}{sub(/ .*/,"",$2);print $2}'   SIGINT 
test-name
$ echo "a -bc d-e -fe -ntest-name -ntest" | awk 'BEGIN{FS="-n *"}{sub(/ .*/,"",$2);print $2}'
Further examples and what would be expected as a result.
$ echo "-ntest-name -ntest" | ...
test-name
$ echo " -n test-name -n test-n" | ...
test-name
$ echo "-na test-name -n test-n" | ...
test-n
$ echo "- n-name -nn test" | ...
n
$ echo "-a -e -i -o" | ...
$ echo "-an -en --n foo" | ...
$ echo "-nbar" | ...
bar
sed would also be a option.
Could this be done with a one-liner? Thank you.

One awk approach:
$ echo "a -n test-name -bc d-e -fe -ntest" | awk '{line=substr($0,$0~/^-n/ ? 3 : index($0," -n")+3); split(line,a); print a[1]}'
test-name
$ echo "a -bc d-e -fe -ntest-name -ntest" | awk '{line=substr($0,$0~/^-n/ ? 3 : index($0," -n")+3); split(line,a); print a[1]}'
test-name
$ echo "-ntest-name a -bc d-e -fe -ntest" | awk '{line=substr($0,$0~/^-n/ ? 3 : index($0," -n")+3); split(line,a); print a[1]}'
test-name
NOTES:
could be further modified if there's an additional delimiter after the value that we need to filter for, eg, echo "-ntest-name|new_command" or echo "a b -n test-name; next_command"; would need to know the potential set of additional delimiters
assumes the input has a valid -n to process otherwise this will print everything from the 3rd input character up to the 1st space (eg, echo "test-name" => st-name; this could be addressed with additional code

This might work for you (GNU getopt and sed):
getopt -auo :n: -- -n test-name -bc d-e -fe -ntest |
sed -E 's/^ -n (\S+).*/\1/p;d'
Or if you prefer:
getopt -auo :n: -- -n test-name -bc d-e -fe -ntest |
awk '/^ -n /{print $2}'
Returns the first -n argument.
N.B. The -u option to getopt returns the argument unquoted.

Related

Assign variable to cut -f field

Using cut, I want to know how to use it as:
awk -v id=3 -v RS= -F '::' '($1==id) {print $3}' jenny | a=1 ;cut -d$'\n' -f$a
I want to use it in a loop where i is replaced with, e.g., -f 1...3
Input
0::chkconfig --list autofs::
autofs 0:off 1:off 2:on 3:on 4:on 5:on 6:off
1::grep "^PROMPT=" /etc/sysconfig/init::
PROMPT=yes
2::rpm -q prelink::
prelink-0.4.0-2.el5
3::if [ -z "$(grep -l "hard core" /etc/security/limits.conf /etc/security/limits.d/*)" ]; then echo "empty"; else echo -e "$(grep -l "hard core" /etc/security/limits.conf /etc/security/limits.d/*)"; fi::
/etc/security/limits.conf
/etc/security/limits.d/test
4::sysctl fs.suid_dumpable::
fs.suid_dumpable = 0
5::stat /etc/motd::
File: `/etc/motd'
Size: 17 Blocks: 16 IO Block: 4096 regular file
Device: fd00h/64768d Inode: 10125343 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2019-04-09 07:56:19.000000000 +0500
Modify: 2019-03-30 19:22:13.000000000 +0500
Change: 2019-03-30 19:22:13.000000000 +0500
Expected Output
/etc/security/limits.conf
/etc/security/limits.d/test
As field 1 and field currently it's all coming in $3. I tried separating with newline in awk; it doesn't seem to catch.
To get your desired output from the given input, try:
$ awk '/^$/{f=0} f{print} /3::/{f=1}' file
/etc/security/limits.conf
/etc/security/limits.d/test
To get only one output line as selected with a variable i:
$ awk -v i=1 '/3::/{n=NR+i} n==NR' file
/etc/security/limits.conf
$ awk -v i=2 '/3::/{n=NR+i} n==NR' file
/etc/security/limits.d/test
The awk variable i can, of course, be set to the value of a shell variable i:
$ i=2
$ awk -v i="$i" '/3::/{n=NR+i} n==NR' file
/etc/security/limits.d/test
The stanza can also be selected from a variable:
$ i=2
$ k=3
$ awk -v i="$i" -v k="$k" -F:: '$1==k{n=NR+i} n==NR' file
/etc/security/limits.d/test
How it works:
-v i="$i" -v k="$k"
These options set awk variable i and k to the values of the shell variables $i and $k, respectively.
-F::
This sets the field separator to ::.
$1==k {n=NR+i}
If the first field of the current line equals the variable k, then set variable n to the current line number, NR, plus i.
n==NR
If the current line number, NR, is n, then print this line.
With sed:
$ id=3; sed -En "/^$id::/,/^$/{/^[[:blank:]]*\//p}" jenny
/etc/security/limits.conf
/etc/security/limits.d/test
Explanations:
Your shell will interpret the command and replace id by its value.
/^$id::/,/^$/{} the scope {} will be executed only between the lines that starts with the value of id followed by :: (/^$id::/) until an empty line (/^$/)
/^[[:blank:]]*\//p for the lines that start with some POSIX blank character class (e.g. space/tab) followed by / print the line. This will print your two paths.
To specify a line:
$ id=3; line=1; sed -En "/^$id::/,/^$/{/^[[:blank:]]*\//p}" jenny | cut -d$'\n' -f"$line"
/etc/security/limits.conf
$ id=3; line=2; sed -En "/^$id::/,/^$/{/^[[:blank:]]*\//p}" jenny | cut -d$'\n' -f"$line"
/etc/security/limits.d/test
$ id=3; line=1; sed -En "/^$id::/,/^$/{/^[[:blank:]]*\//p}" jenny | sed -n "${line}p"
/etc/security/limits.conf
$ id=3; line=2; sed -En "/^$id::/,/^$/{/^[[:blank:]]*\//p}" jenny | sed -n "${line}p"
/etc/security/limits.d/test
Assuming you want to build onto your previous question rather than coming up with a completely different approach
$ awk -v id=3 -v lineNr=1 -v RS= -F '::' '$1==id{ split($3,lines,/\n/); print lines[lineNr+1] }' file
/etc/security/limits.conf
$ awk -v id=3 -v lineNr=2 -v RS= -F '::' '$1==id{ split($3,lines,/\n/); print lines[lineNr+1] }' file
/etc/security/limits.d/test

Piping commands into awk script

cat sample.log.txt|
grep INext-DROP-DEFLT|
sed -e 's/^.*SRC=//' -e 's/ .*DPT=/:/' -e 's/ .*$//' |
sort|
uniq|
ip.awk
I'm trying to send this command to an awk script but I don't know how to pipe it. The ip.awk is the script I want to send it to

Executing Openstack-Rally test cases

I have Openstack installed in my Ubuntu server. I need to run all Rally test cases. I did rally deployment. Now I am able to execute single JSON file and getting the HTML and XML output.
eg:
root#ubuntu:/usr/share/rally/samples/tasks/scenarios/nova# rally task start list-images.json
This way I can execute individual JSON files only.
My requirement:
I have around 250 JSON files to be executed. How to execute them all in one shot?
What tools does the Openstack framework have to execute the entire rally cases(JSON files)?
Actually, you should not want to run 200 separated files. You would like to run one task that contains them. Rally allows you to put as many as you want test cases in single file. For example:
---
NovaServers.boot_and_delete_server:
-
args:
flavor:
name: "m1.tiny"
image:
name: "^cirros.*uec$"
force_delete: false
runner:
type: "constant"
times: 10
concurrency: 2
context:
users:
tenants: 3
users_per_tenant: 2
NovaServers.boot_and_list_server:
-
args:
flavor:
name: "m1.tiny"
image:
name: "^cirros.*uec$"
detailed: True
runner:
type: "constant"
times: 1
concurrency: 1
context:
users:
tenants: 1
users_per_tenant: 1
Take into account that Rally accept jinja2 templates, so you can use all features of jinja2 including "file includ options" Take a look here:
https://rally.readthedocs.io/en/latest/tutorial/step_5_task_templates.html
The best way is to write a script to run all tasks
ex:
#!/bin/bash
cd `dirname $0`
time=`date +%H:%M:%S`
mkdir -p testcase_result/$time
testcase_file=testcase_result/$time/rally_testcase.txt
total_file=testcase_result/$time/rally_total.txt
rally_task_dir=source/samples/tasks/scenarios
#keystone
keystone_case=`find $rally_task_dir/keystone -name "*.yaml"`
keystone_num=`grep -rn '\<Keystone' $keystone_case | wc -l`
echo "Keystone Testcases Number: "$keystone_num > $total_file
echo "Keystone" > $testcase_file
grep -rn '\<Keystone' $keystone_case | awk '{print NR":",$2}' >> $testcase_file
sed -i 's/Keystone.*\.//g' $testcase_file
#glance
glance_case=`find $rally_task_dir/glance -name "*.yaml"`
glance_num=`grep -rn '\<Glance' $glance_case | wc -l`
echo "Glance Testcases Number: "$glance_num >> $total_file
echo "" >> $testcase_file
echo "Glance" >> $testcase_file
grep -rn '\<Glance' $glance_case | awk '{print NR":",$2}' >> $testcase_file
sed -i 's/Glance.*\.//g' $testcase_file
#nova
nova_case=`find $rally_task_dir/nova -name "*.yaml"`
nova_num=`grep -rn '\<Nova' $nova_case | wc -l`
echo "Nova Testcases Number: "$nova_num >> $total_file
echo "" >> $testcase_file
echo "Nova" >> $testcase_file
grep -rn '\<Nova' $nova_case | awk '{print NR":",$2}' >> $testcase_file
sed -i 's/Nova.*\.//g' $testcase_file
#neutron
neutron_case=`find $rally_task_dir/neutron -name "*.yaml"`
neutron_num=`grep -rn '\<Neutron' $neutron_case | wc -l`
echo "Neutron Testcases Number: "$neutron_num >> $total_file
echo "" >> $testcase_file
echo "Neutron" >> $testcase_file
grep -rn '\<Neutron' $neutron_case | awk '{print NR":",$2}' >> $testcase_file
sed -i 's/Neutron.*\.//g' $testcase_file
#cinder
cinder_case=`find $rally_task_dir/cinder -name "*.yaml"`
cinder_num=`grep -rn '\<Cinder' $cinder_case | wc -l`
echo "Cinder Testcases Number: "$cinder_num >> $total_file
echo "" >> $testcase_file
echo "Cinder" >> $testcase_file
grep -rn '\<Cinder' $cinder_case | awk '{print NR":",$2}' >> $testcase_file
sed -i 's/Cinder.*\.//g' $testcase_file
#total
let total=$keystone_num+$glance_num+$nova_num+$neutron_num+$cinder_num
echo "Total Testcases Number: $total" >> $total_file
sed -i 's/:$//' $testcase_file
# Run Scripts tests
cd testcase_result/$time
for i in ../../rally_scripts/*.sh
do
bash $i
done

Linux Grep or Awk to find strings and store into array

I would like to print the string in the following pattern. And I would like to store it in a array. Please help me, I need O/p as follows
test11
orcl
My commands/Tries
egrep -i ":Y|:N" /etc/oratab | cut -d":" -f1 | grep -v "\#" | grep -v "\*" | tr -d '\n' | sed 's/ /\n/g' | awk '{print $1}'
Above commands O/p:
test11orcl
Contents of Oratab will be as follows,
[oracle#rhel6112 scripts]$ cat/etc/oratab
#
# This file is used by ORACLE utilities. It is created by root.sh
# and updated by the Database Configuration Assistant when creating
# a database.
# A colon, ':', is used as the field terminator. A new line terminates
# the entry. Lines beginning with a pound sign, '#', are comments.
#
# Entries are of the form:
# $ORACLE_SID:$ORACLE_HOME:<N|Y>:
#
# Multiple entries with the same $ORACLE_SID are not allowed.
#
#
test11:/u01/app/oracle/product/11.2.0/dbhome_1:N
orcl:/u01/app/oracle/product/10.2.0/db_1:N
End of Cat Output
From the above file am trying to extract the STRING before the :/
As a start, try this:
$ cat input.txt
test11:/u01/app/oracle/product/11.2.0/dbhome_1:N
orcl:/u01/app/oracle/product/10.2.0/db_1:N
$ awk -F: '{print $1}' input.txt
test11
orcl
update
Using bash:
#!/bin/bash
ARRAY=()
while read -r line
do
[[ "$line" = \#* ]] && continue
data=$(awk -F: '{print $1}' <<< $line)
ARRAY+=($data)
done < input.txt
for i in "${ARRAY[#]}"
do
echo "$i"
done
In action:
$ ./db.sh
test11
orcl
You could use sed also,
sed -r 's/^([^:]*):.*$/\1/g' file
Example:
$ cat cc
test11:/u01/app/oracle/product/11.2.0/dbhome_1:N
orcl:/u01/app/oracle/product/10.2.0/db_1:N
$ sed -r 's/^([^:]*):.*$/\1/g' cc
test11
orcl
OR
$ sed -nr 's/^(.*):\/.*$/\1/p' file
test11
orcl

Awk or grep question

I have this datafile
[abc]
def
ghi
[jkl]
[mno]
From this file; i can run grep and easily get all lines that have "[" in them. How can I get the contents of text inside "[]".
For example:
abc
jkl
mno
Thanks
Give this a try:
sed -n 's/\[\([^]]*\)\]/\1/p'
or
awk -F "[][]" '$2 != "" {print $2}'
or
grep -Po '(?<=\[)[^]]*(?=])'
sed -n 's/\[\(.*\)\]/\1/p' file
Explanation: -n suppresses the printing of each line to STDOUT, but the /p at the end of the regex re-enables this behavior causing all matching lines to be printed. The regex itself matches everything between brackets and replaces the entire line with it.
grep "\[" | sed -e 's/\[//' -e 's/\]//'
here's how you can do it with awk
$ cat file
[abc]
def [ xxx]
ghi
[jkl]
[mno]
[zz
zzzz]
$ awk 'BEGIN{RS="]";FS="["}/\[/{print $NF }' file
abc
xxx
jkl
mno
zz
zzzz
Ruby(1.9+)
ruby -0777 -ne 'puts $_.scan(/\[(.*?)\]/m)' file
Or you can do it with just the shell
$ var=$(<file)
$ IFS="]"
$ set -- $var
$ for i in $#; do echo ${i##*[}; done