Sed and Awk - Adding a line to config file - sed

I need to add partition to a config file using sed and awk. How can i do that ?
like lets say I have a path /test1 in the partition /dev/sda3 and I need to add /dev/sda3 to a config file with its name(part3). Lets assume config file is configtest.config
I need to add to in the third line of configtest.config following :
part3 /dev/sda3
How can I do that using sed and awk ? I know to read the partition
i.e
df /test1 | awk '/^\/dev/ {$1}'
I get
/dev/sda3
but I do not know how to add this partition to third line of config file with its name (part3)
I want to use sed and awk.
Thanks !

var=$(df /test1 | sed -rn '2s#([^0-9]+([0-9]+)).*#part\2 \1#p')
sed -i "3i $var" configtest.config

df /test1 |
awk 'NR==FNR{if (/^\/dev/) part=$1; next} 1; FNR==3{print "part3",part}' - configtest.config
If you want to overwrite the original file with the result then it's just:
df /test1 |
awk 'NR==FNR{if (/^\/dev/) part=$1; next} 1; FNR==3{print "part3",part}' - configtest.config > tmp &&
mv tmp configtest.config

Related

Prefix the contents of a file using content of another file having a single line

I am trying to insert the contents of a file1.txt into file2.txt using sed. The content of file1.txt is just a single line, which is a path.
I want it to be added as a prefix to each line in file2.txt as well as add another / character.
$ cat file1.txt
/psot/rot8888/orce/db/tier/data/tine
$ cat file2.txt
o1_mf_users_abchwfg_.dbf
o1_mf_toptbs2_abchrq0_.dbf
o1_mf_toptbs1_abchrl2_.dbf
o1_mf_toptbs1_abchtlf_.dbf
Desired output should be like:
/psot/rot8888/orce/db/tier/data/tine/o1_mf_users_abchwfg_.dbf
/psot/rot8888/orce/db/tier/data/tine/o1_mf_toptbs2_abchrq0_.dbf
/psot/rot8888/orce/db/tier/data/tine/o1_mf_toptbs1_abchrl2_.dbf
/psot/rot8888/orce/db/tier/data/tine/o1_mf_toptbs1_abchtlf_.dbf
Tried command:
$ sed '/o1/ r file1.txt' file2.txt >> test.txt
$ cat test.txt
o1_mf_users_abchwfg_.dbf
/psot/rot8888/orce/db/tier/data/tine
o1_mf_toptbs2_abchrq0_.dbf
/psot/rot8888/orce/db/tier/data/tine
o1_mf_toptbs1_abchrl2_.dbf
/psot/rot8888/orce/db/tier/data/tine
o1_mf_toptbs1_abchtlf_.dbf
/psot/rot8888/orce/db/tier/data/tine
You can use pr for this without having to worry about sed metacharacters, delimiters, etc.
$ cat ip.txt
abcd.xyz
123.txt
foo_baz.txt
$ cat f1
/a/b/c/d/
$ pr -mts"$(< f1)" /dev/null ip.txt
/a/b/c/d/abcd.xyz
/a/b/c/d/123.txt
/a/b/c/d/foo_baz.txt
Where -m allows pasting files parallely and -s is the separator between the files to be merged. Here, /dev/null is used as a dummy for one of the files as only the separator has to be prefixed.
If you need to add some more characters after the contents of file containing the prefix:
$ cat ip.txt
abcd.xyz
123.txt
foo_baz.txt
$ cat f1
/a/b/c/d
$ pr -mts"$(< f1)"'/' /dev/null ip.txt
/a/b/c/d/abcd.xyz
/a/b/c/d/123.txt
/a/b/c/d/foo_baz.txt
This will work using any awk in any shell on every UNIX box:
$ awk 'NR==FNR{p=$0; next} {print p "/" $0}' file1 file2
/psot/rot8888/orce/db/tier/data/tine/o1_mf_users_abchwfg_.dbf
/psot/rot8888/orce/db/tier/data/tine/o1_mf_toptbs2_abchrq0_.dbf
/psot/rot8888/orce/db/tier/data/tine/o1_mf_toptbs1_abchrl2_.dbf
/psot/rot8888/orce/db/tier/data/tine/o1_mf_toptbs1_abchtlf_.dbf
This might work for you (GNU sed):
sed '1h;1d;G;s/\(.*\)\n\(.*\)/\2\1/' file1 file2
Copy file1 into the hold space and append it to each line in file2. Using regexp and back references, manipulate the two lines into one in the correct order.
Alternative:
sed 'x;s/.*/cat file1/e;G;s/\n//' file2
Insert file1 into the hold space, append the current line of file2, and remove the newline connecting them.
A third way:
sed 'r file1' file2 | sed -E 'N;s/(.*)\n(.*)/\2\/\1/'

rename batch files in folder using a textfile

I have a folder of files that start with specific strings and would like to replace part of their strings using the corresponding column from textfile
Folder with files
ABC_S1_002.txt
ABC_S1_003.html
ABC_S1_007.png
NMC_D1_002.png
NMC_D2_003.html
And I have a text file that has the strings to be replaced as:
ABC ABC_newfiles
NMC NMC_extra
So the folder after renaming will be
ABC_newfiles_S1_002.txt
ABC_newfiles_S1_003.html
ABC_newfiles_S1_007.png
NMC_extra_D1_002.png
NMC_extra_D2_003.html
I tried file by file using mv
for f in ABC*; do mv "$f" "${f/ABC/ABC_newfiles}"; done
How can I read in the textfile that has the old strings in first column and replace that with new strings from second column? I tried
IFS=$'\n'; for i in $(cat file_rename);do oldName=$(echo $i | cut -d $'\t' -f1); newName=$(echo $i | cut -d $'\t' -f2); for f in oldName*; do mv "$f" "${f/oldName/newName}"; done ; done
Did not work though.
This might work for you (GNU parallel and rename):
parallel --colsep ' ' rename -n 's/{1}/{2}/' {1}* :::: textFile
This will list out the rename commands for each line in textFile.
Once the output has been checked, remove the -n option and run for real.
For a sed solution, try:
sed -E 's#(.*) (.*)#ls \1*| sed "h;s/\1/\2/;H;g;s/\\n/ /;s/^/echo mv /e"#e' testFile
Again, this will echo the mv commands out, once checked, remove echo and run for real.
Review the result of
sed -r 's#([^ ]*) (.*)#for f in \1*; do mv "$f" "${f/\1/\2}"; done#' textfile
When that looks well, you can copy paste the result or wrap it in source:
source <(sed -r 's#([^ ]*) (.*)#for f in \1*; do mv "$f" "${f/\1/\2}"; done#' textfile)

How to extract text from file to file using sed or grep?

My example string is in txt file /www/meteo/last.txt:
a:3:{i:0;s:4:"6.13";i:1;s:5:"19.94";i:2;s:5:"22.13";}
I would like to get line by line 3 numbers from that file to a new file.
(those values is temperature so they are changing in time - every 10 minutes)
New file /www/meteo/new.txt: (line by line)
6.13
19.94
22.13
Try this awk method
awk -F'"' 'BEGIN{OFS="\n"} {print $2,$4,$6}' last.txt > new.txt
OutPut:
cat new.txt
6.13
19.94
22.13
Or, if you wanted to use sed or grep:
sed -r 's/([^"]*)("[^"]*")([^"]*)/\2\n/g;s/"//g' /www/meteo/last.txt
grep -Eo '"[^"]*"' /www/meteo/last.txt | sed 's/"//g'
If you want a specific value, lets say the second temperature in quotes you can use sed:
grep -Eo '"[^"]*"' /www/meteo/last.txt | sed -n '2p'

How can I remove lines in which length of a field exceeds some threshold using awk or sed?

I have the file test.txt similar to that:
aa:bbbbbb:22.3
a:bb:33.2
a:bbbb:22.3
aaaa:bb:39.9
I know how to count and sort them like:
awk -F ':' '{print $2}' test.txt | awk '{print length($0),$0}' | sort -nr
Now I want to remove the 1st and 3rd lines from the file because the length of the second field (containing "b") in those lines is larger than 3. How can I do that using awk/sed? Thanks.
With awk:
This will output the lines whose 2nd field is >3:
$ awk -F: 'length($2)>3' file
aa:bbbbbb:22.3
a:bbbb:22.3
To do the opposite:
$ awk -F: 'length($2)<=3' file
a:bb:33.2
aaaa:bb:39.9
Code for sed:
sed '/.*:..:.*/!d' file
or more general:
sed '/.*:.\{2\}:.*/!d' file

unix sed, replace field at a specific row and column in the same file

I have a text file with 4 columns delimited by comma.
As I am reading each record in a loop, I want to add a value to the 5th column depending on a condition.
So if I know the row number and column number, how can I use awk/sed commands to replace/set value at that particular field without using temporary files?
I want to update the file (directly) that I am reading from
inp.txt
a,b,c,d
e,f,g,h
i,j,k,l
Thanks,
-sri
I can't speak for sed, but the purpose of awk isn't to edit files in place but to write to stdout.
But anyway, here's a solution you don't need a loop for, pretending the condition is that the entry in column 4 is an h.
awk -F ',' '{ if ($4 == "h") print $0",z"; else print $0","}' inp.txt > out.txt
output:
a,b,c,d,
e,f,g,h,z
i,j,k,l,
You cannot directly edit the file with either awk or sed. Some versions of sed have an option (-i) that works with a temporary file and overwrites the original file, but it does not actually edit the file in place. This is not a big deal. Just do:
$ awk 'NR==5{ $(NF+1) = "new value"}1' OFS=, FS=, input-file > tmp.$$
$ mv tmp.$$ input-file
To add a new column to row 5 of input-file. If you wish, you can use ed to edit the file, but it makes more sense to use a temporary file. If you want to pretend that you aren't using a temporary file, and your sed supports -i, you can do the same thing with:
sed -i '5s/$/,new value/' input-file
Even though most utilitites do not allow in-place modification of the file, it is simple to use one of the following sh functions to emulate that behavior using temporary files:
edit() { local f=$1; shift; "$#" < $f > $f.$$ && mv $f.$$ $f; } # Break hard links
edit() { local f=$1; shift; "$#" < $f > $f.$$ && cat $f.$$ > $f && rm $f.$$; }
With either of these, you could use awk to give the appearance of editing files in-place using edit filename awk awk-cmds. The first version breaks hard links, but uses slightly less IO.
perl -i -F, -lane 'if($.==<row number>){$F[<column_number>-1]+=<add your stuff here>}print join(",",#F)' your_file
tested below:
>cat temp
b,c,d,g
r,g,d,s
execute for changing the 3rd column in second row:
>perl -i -F, -lane 'if($.==2){$F[2]=10}print join(",",#F)' temp
> cat temp
b,c,d,g
r,g,10,s
You mean like this?
this is the version don't using any temporary files.
[a#b ~]$ cat tmp | sed 's_^\(.*\),\(.*\),\(.*\),\(.*\)_\1,\2,\3,\4_g'
inp.txt
a,b,c,d
e,f,g,h
i,j,k,l
[a#b ~]$ cat tmp | sed 's_^\(.*\),\(.*\),\(.*\),\(.*\)_\1,sth,\3,\4_g'
inp.txt
a,sth,c,d
e,sth,g,h
i,sth,k,l
[a#b ~]$ sed -ie 's_^\(.*\),\(.*\),\(.*\),\(.*\)_\1,sth,\3,\4_g' tmp
[a#b ~]$ cat tmp
inp.txt
a,sth,c,d
e,sth,g,h
i,sth,k,l
Cheers,