Extracting the name from a line [closed] - shell

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
A B 5 C Hello: XYZ 'Main Search String', Searching In: '[Name] = "I just want this" AND [State] = Active ('NAME', 'ACT')
How to extract this string: I just want this
grep "Main Search String" filename | awk -F"tab" '{print $6}' | ??

Using awk
awk -F\" '/Main Search String/ {print $2}' file
I just want this

using grep
grep -Po "\[Name\] = \"\K[^\"]*" file
grep -Po "(?<=\[Name\] = \")[^\"]*" file

sed -n 's/.*\[Name\] = "\([^"]*\)".*/\1/p' YourFile
assuming the content is betwween " and for the tag [Name] on any line of your input file

If you want more fun :)
$ cat /tmp/delme
A B 5 C Hello: XYZ 'Main Search String', Searching In: '[Name] = "I just want this" AND [State] = Active ('NAME', 'ACT')
$ cat /tmp/delme | perl -e 'while (<>) { if ( /.*[Name] = \"(.*)\"/ ) { print "$1\n"; } };'
I just want this
With this you can use the whole regex and pattern match things provided by perl...and perl is on almost every system as I know.Give it a try! ;)
EDITED for pattern found case:
$ cat /tmp/delme | perl -e 'while (<>) { print "TEXT: ";print; if ( /.*Main Search String.*\[Name] = "(.*)\"/ ) { print "RESULT: $1\n"; } };'
TEXT: A B 5 C Hello: XYZ 'Main Search String', Searching In: '[Name] = "I just want this" AND [State] = Active ('NAME', 'ACT')
RESULT: I just want this
TEXT: A B 5 C Hello: XYZ 'Not Search String', Searching In: '[Name] = "I just want this" AND [State] = Active ('NAME', 'ACT')

Got it in 13 characters plus the file name:
cut -d\" -f 2 text.txt
This command cuts the text into columns separated by the double-quotes. (-d\") That creates three columns. It prints out the second column with your answer (-f 2).
Like Lutz Horn said, you need to provide a bigger data set to test any of these commands. Many of them will fail if they do not represent the complete pattern they need to parse.

Related

awk script for copy/paste part of string [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 21 days ago.
This post was edited and submitted for review 21 days ago.
Improve this question
Problem:
I have several config files (ProgramName.conf) that need to be edited with awk or sed. The first line contains several letters in place after ":" and end with "]" ProgramName. Or copy filename (it's same as ProgramName). I need to copy ProgramName to the 4th between "command=docker-compose run --rm --name" and "artisan". After conteiner name always word "artisan" in place.
Upd
Thanks for answers, problem solved!
input:
[program:ProgramName]
process_name=
directory=
command=docker-compose run --rm --name artisan some text
target output:
[program:ProgramName]
process_name=
directory=
command=docker-compose run --rm --name ProgramName artisan some text
If ed is available/acceptable, something like:
#!/bin/sh
ed -s file.txt <<-'EOF'
/^\[program:.*\]$/t/^command=/
s/^\[.*:\(.*\)\]$/ \1/
-;+j
,p
Q
EOF
In one-line
printf '%s\n' '/^\[program:.*\]$/t/^command=/' 's/^\[.*:\(.*\)\]$/ \1/' '-;+j' ,p Q | ed -s file.txt
Change Q to w if in-place editing is required.
Remove the ,p to silence the output.
gawk -i inplace '
BEGIN { RS = ORS = ""; FS = OFS = "\n" }
match($1, /^\[program:(.*)\]/, a) {
for (i = 2; i <= NF; ++i)
if ($i ~ /^command=docker-compose run --rm --name/)
$i = "command=docker-compose run --rm --name " a[1]
}
{ print $0 RT }' file
Study the GNU Awk manual for details.
I would harness GNU AWK for this task following way, let file.txt content be then
[program:ProgramName]
process_name=
directory=
command=docker-compose run --rm --name
then
awk 'BEGIN{FS="]|:|\\["}/^\[program:/{name=$3;n=NR}NR==n+3{$0=$0 " " name}{print}' file.txt
gives output
[program:ProgramName]
process_name=
directory=
command=docker-compose run --rm --name ProgramName
Explanation: I inform GNU AWK that field separator (FS) is ] or : or [ then for line starting with [program: I store third column value as name and number of row (NR) as n, then for line which is three lines after thtat happen i.e. number row equals n plus three I append space and name to line and set that as line value, for every line I print it. Be warned that it does modify
to the third line
to comply with your requirement, therefore make sure it is right place do change for all your cases.
(tested in GNU Awk 5.0.1)

Best way to alter a file in a bash script [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 2 years ago.
Improve this question
i have a file that have variables and values
objective: open the file and replace all id by input id
[FILE]
var1 = 2
id = 3
var3 = 5
id = 12
var4 = 5
and i can't replace the id values to new ones.
here's my code, any help or something will help. thanks
#!/bin/bash
filename=$1
uuid=$2
input="./$filename"
# awk -v find="id " -v field="5" -v newval="abcd" 'BEGIN {FS=OFS="="} {if ($1 == find) $field=newval; print $1}' $input
while IFS= read -r line
do
awk -v find="id " -v field="5" -v newval="abcd" 'BEGIN {FS=OFS="="} {if ($1 == find) $field=newval;}' $input
echo $line
done < "$input"
expected output
execute
./myscript.sh file.cnf 77
expected output:
[FILE]
var1 = 2
id = 77
var3 = 5
id = 77
var4 = 5
I think sed is the right tool for this. You can even use its -i switch and update the file in-place.
$ cat file.txt
var1 = 2
id = 3
var3 = 5
id = 12
var4 = 5
$ NEW_ID=1234
$ sed -E "s/(id\s*=\s*)(.+)/\1${NEW_ID}/g" file.txt
var1 = 2
id = 1234
var3 = 5
id = 1234
var4 = 5
The string inside the quotes is a sed script for substituting some text with different text, and its general form is s/regexp/replacement/flags where "regexp" stands for "regular expression".
In the above example, the script looks for the string "id = ..." with any number of spaces or tabs around the "=" character. I divided the regexp into 2 groups (using parentheses) because we only want to replace the part to the right of the "=" character, and I don't think sed allows partial substitutions, so as a workaround I used \1 in the "replacement", which inserts the contents of the 1st group. The ${NEW_ID} actually gets evaluated by the shell so the value of the variable ("1234") is already part of the string by the time sed processes it. The g at the end stands for "global" and is probably redundant in this case. It makes sure that all occurrences of the regex on every line will get replaced; otherwise sed would only replace the first occurrence on each line.
Not sure. Bash scripts are extremely sensitive. I'm guessing your touch is what is causing this issue for a couple of reasons.
First whenever you touch a file name is should not consist of an operand or prefix unliss it is part of the shell script and $filename is shell or inline block quote. Touch is usually used for binaries or high priority data objects.
Second I'd try changing input and adjusted to $done and instead of echoing the $line echo the entire script using esac or end if instead of a do while loop.

Grep string if it has multiple match [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
It was hard to formulate a question, better i will show example.
Txt file has these lines
city:state:address
city:state
city:
I need to extract strings where
a) only one occurrences of :
b) only one occurrences of : and has value after :
c) two occurrences of :
and put these strings to deferent files, so one file will contain all strings with
city:state:address second with city:state third one city:
Note: File has many such strings. Not obligatory to create three files in one command. It will be enough one command where i may define how many : string should contain.
Use these invocations of grep and pipe the output into different files:
grep -E "^[^:]+:\s*$" file.txt
grep -E "^[^:]+:[^:]+$" file.txt
grep -E "^[^:]+:[^:]+:.*$" file.txt
It looks for something that is not : with the regex [^:]+. It uses ^ and $ at the begin and end to match the whole input line.
This is a job for awk, not grep. All you need is:
awk -F':' '
NF==3 { print > "file_c"; next }
{ print > ($2=="" ? "file_a" : "file_b") }
' file
and that'll create all the files you want in one pass of your input file.
If you have more fields and more rules just write them all down so they're mutually exclusive, e.g. you could implement the above as:
NF==3 { print > "file_c" }
NF==2 && $2=="" { print > "file_a" }
NF==2 && $2!="" { print > "file_b" }

Bash how to get text in file [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I file /tmp/txt
contents of the file: aaa aaa aaa _bbb bbb bbb
I need to save the file /tmp/txt_left: aaa aaa aaa
I need to save the file /tmp/txt_right: bbb bbb bbb
!!! attention seeking solutions without the use of variables !!!
awk -F '_' '{print $1> "/tmp/txt_left"; print $2 > "/tmp/txt_right" }' /tmp/txt
You could try cutting the line, slitting on the underscore
Cat /tmp/txt | cut -d_ -f 1 > txt_left
A sed way:
Shorter and quicker:
sed -ne $'h;s/_.*$//;w /tmp/txt_left\n;g;s/^.*_//;w /tmp/txt_right' /tmp/txt
Explained: It could be written:
sed -ne '
h; # hold (copy current line in hold space)
s/_.*$//; # replace from _ to end of line by nothing
w /tmp/txt_left
# Write current line to file
# (filename have to be terminated by a newline)
g; # get (copy hold space to current line buffer)
s/^.*_//; # replace from begin of line to _ by nothing
w /tmp/txt_right
# write
' /tmp/txt
Bash as bash
This is not a real variable, I use first argument element for doing the job and restore argument list once finish:
set -- "$(</tmp/txt)" "$#"
echo >>/tmp/txt_right ${1#*_}
echo >>/tmp/txt_left ${1%_*}
shift
I unshift the string at first place in argument line,
do operation on $1, than shift the argument line so no variable is used and in fine, the argument line return in his original state
... and this is a pure bash solution ;-)
Using bash process substitution, tee, and cut:
tee -a >(cut -d _ -f 0 > /tmp/txt_left) >(cut -d _ -f 1 >/tmp/txt_right) < /tmp/txt

shell script to search attribute and store value along with filename

Looking out for a shell script which searches for an attribute (a string) in all the files in current directory and stores the attribute values along with the file name.
e.g File1.txt
abc xyz = "pqr"
File2.txt
abc xyz = "klm"
Here File1 and File2 contains desired string "abc xyz" and have values "pqr" and "klm".
I want result something like this:
File1.txt:pqr
File2.txt:klm
Well, this depends on how do you define a 'shell script'. Here are 3 one-line solutions:
Using grep/sed:
egrep -o "abc xyz = ".*"' * | sed -e 's/abc xyz = "(.*)"/\1/'
Using awk:
awk '/abc xyz = "(.)"/ { print FILENAME ":" gensub("abc xyz = \"(.)\"", "\1", 1) }' *
Using perl one-liner:
perl -ne 'if(s/abc xyz = "(.*)"/$ARGV:$1/) { print }' *
I personally would go with the last one.
Please don't use bash scripting for this.
There is much room for small improvements in the code,
but in 20 lines the damn thing does the job.
Note: the code assumes that "abc xyz" is at the beginning of the line.
#!/usr/bin/python
import os
import re
MYDIR = '/dir/you/want/to/search'
def search_file(fn):
myregex = re.compile(r'abc xyz = \"([a-z]+)\"')
f = open(fn, 'r')
for line in f:
m = myregex.match(line)
if m:
yield m.group(1)
for filename in os.listdir(MYDIR):
if os.path.isfile(os.path.join(MYDIR, filename)):
matches = search_file(os.path.join(MYDIR, filename))
for match in matches:
print filename + ':' + match,
Thanks to David Beazley, A.M. Kuchling, and Mark Pilgrim for sharing their vast knowledge.
I couldn't have done something like this without you guys leading the way.

Resources