I need your help in unix.i have a file where i have a value declared and and i have to replace the value when called. for example i have the value for &abc and &ccc. now i have to substitute the value of &abc and &ccc in the place of them as shown in the output file.
Input File
go to &abc=ddd;
if file found &ccc=10;
no the value name is &abc;
and the age is &ccc;
Output:
go to &abc=ddd;
if file found &ccc=10;
now the value name is ddd;
and the age is 10;
Try using sed.
#!/bin/bash
# The input file is a command line argument.
input_file="${1}"
# The map of variables to their values
declare -A value_map=( [abc]=ddd [ccc]=10 )
# Loop over the keys in our map.
for variable in "${!value_map[#]}" ; do
echo "Replacing ${variable} with ${value_map[${variable}]} in ${input_file}..."
sed -i "s|${variable}|${value_map[${variable}]}|g" "${input_file}"
done
This simple bash script will replace abc with ddd and ccc with 10 in the given file. Here is an example of it working on a simple file:
$ cat file.txt
so boo aaa abc
duh
abc
ccc
abcccc
hmm
$ ./replace.sh file.txt
Replacing abc with ddd in file.txt...
Replacing ccc with 10 in file.txt...
$ cat file.txt
so boo aaa ddd
duh
ddd
10
ddd10
hmm
Related
I need a command that prints data between two strings (Hello and End) along with the file name and file path on each line. Here is the input and output. Appreciate your time and help
Input
file1:
Hello
abc
xyz
End
file2:
Hello
123
456
End
file3:
Hello
Output:
/home/test/seq/file1 abc
/home/test/seq/file1 xyz
/home/test/seq/file2 123
/home/test/seq/file2 456
I tried awk and sed but not able to print the file with the path.
awk '/Hello/{flag=1;next}/End/{flag=0}flag' * 2>/dev/null
With awk:
awk '!/Hello/ && !/End/ {print FILENAME,$0} ' /home/test/seq/file?
Output:
/home/test/seq/file1 abc
/home/test/seq/file1 xyz
/home/test/seq/file2 123
/home/test/seq/file2 456
If your file contains lines above Hello and/or below End, then you can use a flag to control printing as you had attempted in your question, e.g.
awk -v f=0 '/End/{f=0} f == 1 {print FILENAME, $0} /Hello/{f=1}' file1 file2 file..
This would handle the case where your input file contained, e.g.
$cat file
some text
some more
Hello
abc
xyz
End
still more text
The flag f is a simple ON/OFF flag to control printing and placing the end rule first with the actual print in the middle eliminates the need for any next command.
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 3 years ago.
Improve this question
I have two files;
in1.txt:
bbb
ccc
ddd
aaa
ccc
bbb
ddd
in2.txt:
sss
In in1.txt, I want to replace lines from aaa to the first occurence of ddd with the contents of in2.txt.
Desired output:
bbb
ccc
ddd
sss
tl;dr:
$ sed -e "/aaa/,/ddd/c\\$(cat in2.txt)" in1.txt
bbb
ccc
ddd
sss
In detail:
$ sed -e '/START/,/FIN/c\REPLACE_WITH' file
/START/,/FIN/ indicates the range of text to replace - beginning with START and ending with FIN.
The \c is used to replace the previous declared lines with REPLACE_WITH.
Hope this helps.
This might work for you (GNU sed):
sed -e 'x;/x/{x;:a;n;ba};x;/^aaa$/{:b;N;/^ddd$/M!bb;x;s/^/x/;x;r file2' -e 'd}' file1
In order to make the replacement once only , set a flag in the hold space and check every time a line is read in, if that flag has been set. If it has, print the remainder of the file using the n command and a loop.
If the flag has not been set, on encountering the start delimiter, accumulate the the file up until the end delimiter in the pattern space. Set the once only flag and read in the contents of the second file. Finally delete the pattern space.
On top of the nice sed solutions that have been provided, I have added a awk one:
Input files:
$ more in*.txt
::::::::::::::
in1.txt
::::::::::::::
bbb
ccc
ddd
aaa
ccc
bbb
ddd
::::::::::::::
in2.txt
::::::::::::::
sss
command:
awk -v delim1="aaa" -v delim2="ddd" -v target=in2.txt '{if($0 == delim1){test=1;system("cat "target);next}if(test !=1) print;if($0 == delim2){test=0};}' in1.txt
output:
bbb
ccc
ddd
sss
Code:
{
if ($0 == delim1) {
test = 1
system("cat " target)
next
}
if (test != 1) {
print $0
}
if ($0 == delim2) {
test = 0
}
}
Explanations:
-v delim1="aaa" -v delim2="ddd" -v target=in2.txt you pass the 2 delimiters to awk as parameters as well as the file you want to read from (in2.txt)
When you reach the first delimiter, your test variable is set to 1 and you print the content of in2.txt, you jump to next line.
if test variable is different than 1 you print the line (this means that you have not yet encountered the first delimiter)
When you reach the 2nd delimiter you reset test to allow the printing of the rest of the file.
I have one file containing a list of name (refer as file 1):
Apple
Bat
Cat
I have another file (refer as file 2) containing a list of name and details refer:
Apple bla blaa
aaaaaaaaaggggggggggttttttsssssssvvvvvvv
ssssssssiiuuuuuuuuuueeeeeeeeeeennnnnnnn
sdasasssssssssssssssssssssswwwwwwwwwwww
Aeroplane dsafgeq dasfqw dafsad
vvvvvvvvvvvvvvvvuuuuuuuuuuuuuuuuuuuuuus
fcsadssssssssssssssssssssssssssssssssss
ddddddddddddddddwwwwwwwwwwwwwwwwwwwwwww
sdddddddddddddddddddddddddddddwwwwwwwww
Bat sdasdas dsadw dasd
sssssssssssssssssssssssssssssssssssswww
ssssssssssssssssswwwwwwwwwwwwwwwwwwwwwf
aaaaaaaaaawwwwwwwwwwwwwwwwwwwwwwddddddd
sadddddddddddddddddd
Cat dsafw fasdsa dawwdwaw
sssssssssssssssssssssssssssssssssssssss
wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwssss
I need to extract info out of file 2 using the list of names in file 1.
Output file should be something like below:
Apple bla blaa
aaaaaaaaaggggggggggttttttsssssssvvvvvvv
ssssssssiiuuuuuuuuuueeeeeeeeeeennnnnnnn
sdasasssssssssssssssssssssswwwwwwwwwwww
Bat sdasdas dsadw dasd
sssssssssssssssssssssssssssssssssssswww
ssssssssssssssssswwwwwwwwwwwwwwwwwwwwwf
aaaaaaaaaawwwwwwwwwwwwwwwwwwwwwwddddddd
sadddddddddddddddddd
Cat dsafw fasdsa dawwdwaw
sssssssssssssssssssssssssssssssssssssss
wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwssss
Is there any commands for doing this using Linux (Ubuntu)? I am a new Linux user.
This might work for you (GNU sed):
sed 's#.*#/^&/bb#' file1 |
sed -e ':a' -f - -e 'd;:b;n;/^[A-Z]/!bb;ba' file2
Generate a string of sed commands from the first file and pipe them into another sed script which is run against the second file.
The first file creates a regexp for each line which when matched jumps to a piece of common code. If none of the regexps are matched the lines are deleted. If a regexp is matched then further lines are printed until a new delimiter is found at which point the code then jumps to the start and the process is repeated.
$ awk 'NR==FNR{a[$1];next} NF>1{f=($1 in a)} f' file1 file2
Apple bla blaa
aaaaaaaaaggggggggggttttttsssssssvvvvvvv
ssssssssiiuuuuuuuuuueeeeeeeeeeennnnnnnn
sdasasssssssssssssssssssssswwwwwwwwwwww
Bat sdasdas dsadw dasd
sssssssssssssssssssssssssssssssssssswww
ssssssssssssssssswwwwwwwwwwwwwwwwwwwwwf
aaaaaaaaaawwwwwwwwwwwwwwwwwwwwwwddddddd
sadddddddddddddddddd
Cat dsafw fasdsa dawwdwaw
sssssssssssssssssssssssssssssssssssssss
wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwssss
Taking into consideration that each section has to be separated by an empty line, this solution with awk works ok:
while read -r pat;do
pat="^\\\<${pat}\\\>"
awk -vpattern=$pat '$0 ~ pattern{p=1}$0 ~ /^$/{p=0}p==1' file2
done <file1
This solution to work , requires the file to like this:
Apple bla blaa
1 aaaaaaaaaggggggggggttttttsssssssvvvvvvv
2 ssssssssiiuuuuuuuuuueeeeeeeeeeennnnnnnn
3 sdasasssssssssssssssssssssswwwwwwwwwwww
Aeroplane dsafgeq dasfqw dafsad
4 vvvvvvvvvvvvvvvvuuuuuuuuuuuuuuuuuuuuuus
5 fcsadssssssssssssssssssssssssssssssssss
6 ddddddddddddddddwwwwwwwwwwwwwwwwwwwwwww
7 sdddddddddddddddddddddddddddddwwwwwwwww
Bat sdasdas dsadw dasd
8 sssssssssssssssssssssssssssssssssssswww
9 ssssssssssssssssswwwwwwwwwwwwwwwwwwwwwf
10 aaaaaaaaaawwwwwwwwwwwwwwwwwwwwwwddddddd
11 sadddddddddddddddddd
Cat dsafw fasdsa dawwdwaw
12 sssssssssssssssssssssssssssssssssssssss
13 wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwssss
PS: Numbering has been applied by me in order to be able to "check" that awk will return the correct results per section. Numbering is not required in your real file.
If there are not empty lines separating each section then it is much harder to achieve the correct result.
I am working in a linux environment and I would like to get some help on bash scripting to cut down on simple repetition.
I have long list of file names(937 to be exact). In that file on one row there is only one file name there, therefore, total of 937 lines in the file.
I would like to add certain text before the file name and add numbers after the file name in order.
so I would like something like this in the text file.
aa.exe
bb.exe
cc.exe
to
asd aa.exe 1
asd bb.exe 2
asd cc.exe 3
any help will be greatly appreciated.
Just for kicks, here's an awk version:
awk '{print "foo", $0, NR}' files.lst
If files.lst consists of:
a.txt
b.txt
c.txt
...then this will output:
foo a.txt 1
foo b.txt 2
foo c.txt 3
Pure Bash:
while read -r line
do
echo "asd $line $((++i))"
done < inputfile
Here is a simple Python solution, save it in a text file named so.py.
Since you are still using Python v 2.4.2, this code should work with that earlier version:
#!/usr/bin/python
add_text = 'asd' # the string to put in front
fn = open('filenames.txt')
outf = open('outdata.txt', 'w')
i = 1
for filename in fn:
outf.write('%7s %10s %d\n' % (add_text, filename.strip(), i))
i += 1
fn.close()
outf.close()
Expects the names of the files to be in file filenames.txt, and the output generated goes to file outdata.txt.
asd aa.exe 1
asd bb.exe 2
asd cc.exe 3
The text to be added ahead of the filename is fixed in the variable add_text.
To run the script, issue these commands at the Linux prompt:
chmod +x so.py <-- this is only needed once
./so.py <-- to run the script
and it will use the input file to generate the output file.
In vim:
:%s/.\+/\=printf("%s %s %d", "asdf", submatch(0), line("."))/
Supposedly I have this line in my text file which has the following format.
"Title:Author:Price:QtyAvailable:QtySold"
The contents of my text file is shown below
Hello World:Andreas:10.50:10:5
Lord Of The Rings:Duke:50.15:50:20
(some other records...)
1) User inputs Author and Title.
2) If Program locates the Author+Title, it asks user to Update any of the fields available ( for this case Title, Author, Price etc..
3) For example I will like to update the Price of Hello World book.
4) What can I do to tell the program to extract the contents of the Hello World line, and get into 10.50 to replace the price of the book? (assumes new price of the book will be decided by the user's input)
Hope to get my answer.
Thanks in advance to those who helped!
You can use sed like this with variable parameters:
# book title:author to be searched
BOOK="Hello World:Andreas"
# price to be updated
PRICE=11.25
# search and update with original backed up with .bak extension
sed -i.bak 's/\('"$BOOK"'\):[^:]*:/\1:'"$PRICE"':/' file.txt
Explanation:
If you fill-in shell variables into sed command it will look like this:
sed 's/\(Hello World:Andreas\):[^:]*:/\1:11.25:/'
match
"$BOOK" # match literal text i.e. Hello World:Andreas
\($BOOK\) # group this text to be back referenced later
: # match literal :
[^:]* # match 0 or more characters until : is found
: # match a :
replacement
\1 # group # 1 i.e. Hello World:Andreas
: # a literal :
$PRICE # fill in the new price
: # literal :
Essentially this sed command is finding text that has Hello World:Andreas: followed by some price value and then followed by another :. Once this patter is found it is replacing that with back-reference # 1 (which is Hello World:Andreas) followed by a : and then put the new price value and a colon :.
EDIT: You are highly recommended to read some sed tutorial however as per your comment I am providing you command to update quantity:
# book title:author to be searched
BOOK="Hello World:Andreas"
# quantity to be updated
QTY=18
# search and update with original backed up with .bak extension
sed 's/^\('"$BOOK"'\):\([^:]*\):[^"]*:/\1:\2:'"$QTY"':/'
Following is a something to get you started:
Sample Script:
[jaypal:~/Temp] cat s.sh
#!/bin/bash
echo "Author?"
read author
echo "Title?"
read title
grep -c "$title:$author" file > /dev/null # Look for a line with matching values
if [ $? == 0 ]; then # If found then offer to change price
echo "I found the book, Do you want to update price to what?"
read newprice
sed -i "s/\($book:$author\):[^:]*:/\1:$newprice:/" file
fi
Input Data:
[jaypal:~/Temp] cat file
Hello World:Andreas:10.50:10:5
Lord Of The Rings:Duke:50.15:50:20
Execution:
[jaypal:~/Temp] ./s.sh
Author?
Andreas
Title?
Hello World
I found the book, Do you want to update price to what?
40
[jaypal:~/Temp] cat file
Hello World:Andreas:40:10:5
Lord Of The Rings:Duke:50.15:50:20