Filter a text from a specific file and append the output to another file Linux - linux

I am trying to append a text from a file to the another file in Linux using the grep command .
I have a file named "temp1buildVersion.properties" which contain the data
like
Project version: 1.0.5
also, I have another file named buildversion.properties which contain data
VERSION_BUILD=
I want to fetch content from temp1buildVersion.properties" after "Project version:" and append it to an existing file named "buildversion.properties"
so that output of the buildversion.properties will be
VERSION_BUILD=1.0.5
currently, I am doing using the grep command to fetch data and appending output to file " buildversion.properties "
grep 'Project version: ' /tmp/tempbuildVersion.properties | cut -d\ -f3 >> /tmp/buildversion.properties
it comes in two-line How can I append to the same line /or a specific line?
VERSION_BUILD =
1.0.5

You may use this awk:
awk -F ': ' 'FNR==NR {ver=$2; next} /^VERSION_BUILD=/ {print $0 ver}' temp1buildVersion.properties buildversion.properties > _tmp && mv _tmp buildversion.properties
VERSION_BUILD=1.0.5

Another option is using sed to append to the end of the line, e.g.
sed "/VERSION_BUILD/s/\$/$(grep 'Project version: ' /tmp/tempbuildVersion.properties | cut -d\ -f3)/" buildversion.properties
Above your command is simply placed as a command substituion in sed "/VERSION_BUILD/s/\$/$(your_cmd)/" file. You would add sed -i to update the file in place.
You can eliminate the pipeline and cut by simply using awk to isolate the version number and shorten the command a bit, e.g.
sed "/VERSION_BUILD/s/\$/$(awk '/^Project version:/{printf "%s", $NF; exit}' /tmp/tempbuildVersion.properties)/" buildversion.properties

If ed is available/acceptable.
printf '%s\n' 'r temp1buildVersion.properties' 's/^Project version: //' '1,$j' ,p Q | ed -s buildversion.properties
Change Q to w if you're ok with the output and to edit the file buildversion.properties
The script.
#!/usr/bin/env bash
ed -s "$1" <<-EOF
r $2
s/^Project version: //
1,\$j
,p
Q
EOF
You can execute with the files as the arguments.
./myscript buildversion.properties temp1buildVersion.properties

This might work for you (GNU sed):
sed -i '/VERSION_BUILD=/{x;s/.*/cat fileVersion/e;x;G;s/\n.*:\s*//}' fileBuild
Process the build file until a match on a line VERSION_BUILD=.
Swap to the hold space and insert the version file line.
Append the line from the version file to the current line and using pattern matching manipulate the line into the desired format.

Related

Change a letter in a file to uppercase in Shell script

I'm trying to change a specific given letter to uppercase in a file, but I don't know how to do it. The file already exist and I want to do the following
cat merry.txt
I wish you a Merry Christmas
Change e to E so the output will be
cat merry.txt
I wish you a MErry Christmas
Thank you everyone
Try this :
sed 's/e/E/' merry.txt
If your text included more than one occurrence of ā€eā€ on a line, the preceding sed would
have changed just the first occurrence on each line to ā€E.ā€ By appending the global option
g to the end of the s command, you can ensure that multiple occurrences of the string on a line will be changed.
Try to use this :
sed 's/e/E/g' merry.txt
This command converts all e to E.
Or can use :
sed -i 's/e/E/g' merry.txt
Like this:
sed 's/e/\Ue/' Input_File
To edit permanently, add -i switch:
sed -i ...
You can use tr to "translate" a char to another char:
tr 'e' 'E' < file > newfile && mv newfile file
You can also use awk (here, a dynamic approach is used):
find='e'
replace='E'
awk -v f="$find" -v r="$replace" '{gsub(f, r)}1' file > newfile && mv newfile file
With GNU sed, you may use
sed -i 'y/e/E/' file
In all these case, you replace an e with E everywhere in the file and save the contents of the updated file under the same filename.
See a sample demo online:
#!/bin/bash
s='I wish them a Merry Christmas'
find='e'
replace='E'
tr "$find" "$replace" <<< "$s"
awk -v f="$find" -v r="$replace" '{gsub(f, r)}1' <<< "$s"
sed 'y/e/E/' <<< "$s"
Output: I wish thEm a MErry Christmas.

how to show the third line of multiple files

I have a simple question. I am trying to check the 3rd line of multiple files in a folder, so I used this:
head -n 3 MiseqData/result2012/12* | tail -n 1
but this doesn't work obviously, because it only shows the third line of the last file. But I actually want to have last line of every file in the result2012 folder.
Does anyone know how to do that?
Also sorry just another questions, is it also possible to show which file the particular third line belongs to?
like before the third line is shown, is it also possible to show the filename of each of the third line extracted from?
because if I used head or tail command, the filename is also shown.
thank you
With Awk, the variable FNR is the number of the "record" (line, by default) in the current file, so you can simply compare it to 3 to print the third line of each input file:
awk 'FNR == 3' MiseqData/result2012/12*
A more optimized version for long files would skip to the next file on match, since you know there's only that one line where the condition is true:
awk 'FNR == 3 { print; nextfile }' MiseqData/result2012/12*
However, not all Awks support nextfile (but it is also not exclusive to GNU Awk).
A more portable variant using your head and tail solution would be a loop in the shell:
for f in MiseqData/result2012/12*; do head -n 3 "$f" | tail -n 1; done
Or with sed (without GNU extensions, i.e., the -s argument):
for f in MiseqData/result2012/12*; do sed '3q;d' "$f"; done
edit: As for the additional question of how to print the name of each file, you need to explicitly print it for each file yourself, e.g.,
awk 'FNR == 3 { print FILENAME ": " $0; nextfile }' MiseqData/result2012/12*
for f in MiseqData/result2012/12*; do
echo -n `basename "$f"`': '
head -n 3 "$f" | tail -n 1
done
for f in MiseqData/result2012/12*; do
echo -n "$f: "
sed '3q;d' "$f"
done
With GNU sed:
sed -s -n '3p' MiseqData/result2012/12*
or shorter
sed -s '3!d' MiseqData/result2012/12*
From man sed:
-s: consider files as separate rather than as a single continuous long stream.
You can do this:
awk 'FNR==3' MiseqData/result2012/12*
If you like the file name as well:
awk 'FNR==3 {print FILENAME,$0}' MiseqData/result2012/12*
This might work for you (GNU sed & parallel):
parallel -k sed -n '3p\;3q' {} ::: file1 file2 file3
Parallel applies the sed command to each file and returns the results in order.
N.B. All files will only be read upto the 3rd line.
Also,you may be tempted (as I was) to use:
sed -ns '3p;3q' file1 file2 file3
but this will only return the first file.
Hi bro I am answering this question as we know FNR is used to check no of lines so we can run this command to get 3rd line of every file.
awk 'FNR==3' MiseqData/result2012/12*

How to print File name in the same file?

I have a file with around 5 lines and I want to have the file name printed at the end of every line.
for file in *.txt
do
sed -i "1s/\$/${file%%.*}/" "$file"
done
The above code only writes file name in first line, I want to have file name in every line.
The above code only writes file name in first line
This is what the 1 on the beginning of the sed command does: it is an address that selects the lines processed by the command.
In your case, the s command applies only to the first line (because of 1 in front of the command). Remove the 1 from the command and it will apply to all lines of the file:
for file in *.txt
do
sed -i "s/\$/${file%%.*}/" "$file"
done
Read more about sed at https://www.gnu.org/software/sed/manual/sed.html.
Given that you have already learned sed, typing man sed on your terminal will refresh your memory about its commands.
This is a bit hacky, but it does the trick (bash):
filename=<filename>; len=$(wc -l $filename | cut -f1 -d' '); for i in $(seq $len); do echo $filename; done | paste $filename -
And this is cleaner, but needs python installed:
python -c "import sys; print('\n'.join(line.rstrip() + '\t' + sys.argv[1] for line in open(sys.argv[1])))" <filename>

How to generate a UUID for each line in a file using AWK or SED?

I need to append a UUID ( newly generated unique for each line) to each line of a file. I would prefer to use SED or AWK for this activity and take advantage of UUIDGEN executable on my linux box. I cannot figure out how to generate the the UUID for each line and append it.
I have tried:
awk '{print system(uuidgen) $1} myfile.csv
sed -i -- 's/^/$(uuidgen)/g' myfile.csv
And many other variations that didn't work. Can this be done with SED or AWK, or should I be investigating another solution that is not shell script based?
Sincerely,
Stephen.
Using bash, this will create a file outfile.txt with a concatenated uuid:
NOTE: Please run which bash to verify the location of your copy of bash on your system. It may not be located in the same location used in the script below.
#!/usr/local/bin/bash
while IFS= read -r line
do
uuid=$(uuidgen)
echo "$line $uuid" >> outfile.txt
done < myfile.txt
myfile.txt:
john,doe
mary,jane
albert,ellis
bob,glob
fig,newton
outfile.txt
john,doe 46fb31a2-6bc5-4303-9783-85844a4a6583
mary,jane a14bb565-eea0-47cd-a999-90f84cc8e1e5
albert,ellis cfab6e8b-00e7-420b-8fe9-f7655801c91c
bob,glob 63a32fd1-3092-4a72-8c24-7b01c400820c
fig,newton 63d38ad9-5553-46a4-9f24-2e19035cc40d
Just tweaking the syntax on your attempt, something like this should work:
awk '("uuidgen" | getline uuid) > 0 {print uuid, $0} {close("uuidgen")}' myfile.csv
For example:
$ cat file
a
b
c
$ awk '("uuidgen" | getline uuid) > 0 {print uuid, $0} {close("uuidgen")}' file
52a75bc9-e632-4258-bbc6-c944ff51727a a
24c97c41-d0f4-4cc6-b0c9-81b6d89c5b77 b
76de9987-a60f-4e3b-ba5e-ae976ab53c7b c
The right solution is to use other shell commands though since the awk isn't buying you anything:
$ xargs -n 1 printf "%s %s\n" $(uuidgen) < file
763ed28c-453f-47f4-9b1b-b2f972b2cc7d a
763ed28c-453f-47f4-9b1b-b2f972b2cc7d b
763ed28c-453f-47f4-9b1b-b2f972b2cc7d c
Try this
awk '{ "uuidgen" |& getline u; print u, $1}' myfile.csv
if you want to append instead of prepend change the order of print.
Using xargs is simpler here:
paste -d " " myfile.csv <(xargs -I {} uuidgen {} < myfile.csv)
This will call uuidgen for each line of myfile.csv
You can use paste and GNU sed:
paste <(sed 's/.*/uuidgen/e' file) file
This uses the GNU execute extension e to generate a UUID per line, then paste pastes the text back together. Use the -d paste flag to change the delimiter from the default tab, to whatever you want.

Removing line that contains more than one word

I need to remove a line in a specified file if it has more than one word in it using a bash script in linux.
e.g. file:
$ cat testfile
This is a text
file
This line should be deleted
this-should-not.
awk 'NF<=1{print}' testfile
a word being a run of non-whitespace.
Just for fun, here's a pure bash version which doesn't call any other executable (since you asked for it in bash):
$ while read a b; do if [ -z "$b" ]; then echo $a;fi;done <testfile
awk '!/[ \t]/{print $1}' testfile
This reads "print the first element of lines that don't contain a space or a tab".
Empty lines will be output (since they don't contain more than one word).
Easy enough:
$ egrep -v '\S\s+\S' testfile
$ sed '/ /d' << EOF
> This is a text
> file
>
> This line should be deleted
> this-should-not.
> EOF
file
this-should-not.
If you want to edit files in-place (without any backups), you may also use man ed:
cat <<-'EOF' | ed -s testfile
H
,g/^[[:space:]]*/s///
,g/[[:space:]]*$/s///
,g/[[:space:]]/.d
wq
EOF
This should satisfy your needs:
cat filename | sed -n '/^\S*$/p'

Resources