search a keyword in file and replace line next to it - shell

I have a file which requires modification via a shell script.
Need to do the following:
1. search for a keyword in the file.
2. replace the next line to this keyword with my supplied line text.
for e.g., my file has the following text:
(some text)
(some text)
(text_to_search)
(text_to_replace)
(some text)
(some text)
(some text)
I need to search the file for and rewrite the file replace the line leaving the remaining content untouched.
How can this be done?
Regards

awk ' zap==1 {print "my new line goes here"; zap=0; next}
/my pattern/ {zap=1; print $0; next}
{print $0} ' infile > newfile
Assuming I got what you wanted....
var="this is the line of text to insert"
awk -v lin="$var" ' zap==1 {print lin ; zap=0; next}
/my pattern/ {zap=1; print $0; next}
{print $0} ' infile > newfile
the awk internal variable lin, defined: -v lin="$var" is named lin, lin comes from the external bash variable var.

sed -i '/pattern/r/dev/stdin' file
the script will wait for us to enter the newline and press ctrl +d interactively +

cat file
first
second
third
fourth
fiveth
set var = "inserted"
sed '/second/a\'$var file
first
second
inserted
third
fourth
fiveth

Related

Take string from multiple files and copy to new file and print filename into second column in bash

I have multiple files containing this information:
sP12345.txt
COMMENT Method: conceptual translation.
FEATURES Location/Qualifiers
source 1..3024
/organism="H"
/isolate="sP12345"
/isolation_source="blood"
/host="Homo sapiens"
/db_xref="taxon:11103"
/collection_date="31-Mar-2014"
/note="genotype: 3"
sP4567.txt
COMMENT Method: conceptual translation.
FEATURES Location/Qualifiers
source 1..3024
/organism="H"
/isolate="sP4567"
/isolation_source="blood"
/host="Homo sapiens"
/db_xref="taxon:11103"
/collection_date="31-Mar-2014"
/note="genotype: 2"
Now I would like to get the /note="genotype: 3" and copy only the number that is after genotype: copy it to a new textfile and print the filename from which is has been taken as column 2.
Expected Output:
3 sP12345
2 sP4567
I tried this code: but it only prints the first column and not the filename:
awk -F'note="genotype: ' -v OFS='\t' 'FNR==1{++c} NF>1{print $2, c}' *.txt > output_file.txt
You may use:
awk '/\/note="genotype: /{gsub(/^.* |"$/, ""); f=FILENAME; sub(/\.[^.]+$/, "", f); print $0 "\t" f}' sP*.txt
3 sP12345
2 sP4567
$ awk -v OFS='\t' 'sub(/\/note="genotype:/,""){print $0+0, FILENAME}' sP12345.txt sP4567.txt
3 sP12345.txt
2 sP4567.txt
You can do:
awk '/\/note="genotype:/{split($0,a,": "); print a[2]+0,"\t",FILENAME}' sP*.txt
3 sP12345.txt
2 sP4567.txt
With your shown samples, in GNU awk please try following awk code.
awk -v RS='/note="genotype: [0-9]*"' '
RT{
gsub(/.*: |"$/,"",RT)
print RT,FILENAME
nextfile
}
' *.txt
Explanation: Simple explanation would be, passing all .txt files to GNU awk program here. Then setting RS(record separator) as /note="genotype: [0-9]*" as per shown samples and requirement. In main program of awk, using gsub(global substitution) to removing everything till colon followed by space AND " at the end of value of RT with NULL. Then printing value of RT followed by current file's name. Using nextfile will directly take program to next file skipping rest of contents of file, to save sometime for us.

Changing value in entire column of a CSV file using awk

I have CSV file like example below. I wish to change value of mail in every line for the same mail with awk. I used
awk -F ";" '{$18=firstname.lastname#testdata.invali} {print}' example_source_20180619.csv > erm.csv
but got error invalid statement
PNR;GES-SL-SAP;VERT-KANAL-SL-SAP;DSTNR-SAP;BTRBL-FKT;SCHWPKT-TAETIG-SL;SCHWPKT-TAETIG-TXT;BTRBL-TITEL-TXT;ANREDE;NAME;VORNAME;STRASSE;PLZ;ORT;DIENST-TEL-NR;TELEFAX-NR;MOBIL-TEL-NR;E-MAIL-ADR;INTERNET-ADR;P34F-KZ;HD-ANL-BER-KZ;VERT-KANAL-SL;
0000000;0010;2100 ;00602;Referent ;99;Sonstige/kein Schw. ;ohne Titel ;Sir ;John ;Doe ;Paul-Keller-Str. 21 ;92318;Neumarkt i.d.OPf. ;phone;0941/phone;;mail#mail.com;http://web.de ;NO;NO;
awk -F ";" '{OFS=";"; $18="firstname.lastname#testdata.invali"; print;}'
Put strings inside ".
Separate commands using ;.
Set the output separator also to ; so the output is similar to the input.
I guess theres no point in substituting the email address in the first line, so I added a small if below:
awk -F ";" '{ OFS=";"; if (NR != 1) { $18="firstname.lastname#testdata.invali"; } print; }'

How to alter number of columns [with awk] only if a string is in the 1st column of the line while printing changed line and whole text

I want to replace the number of columns, only use 1st and last one for each line containing a >.
But then I want to print the whole file again, with the changed lines like this.
>TRF [name1]
AAAAAAAAAAAAAAAAAAAAAAAAAAATTGGA
ATGGGGGGGGGGGGGGGGGGGGGGGGGC
I have tried with this code but it only returns the changed lines. Thanks.
awk '$1 ~ />/ { print $1" "$NF}' file
You can use:
awk '$1 ~ />/ { $0 = $1 " " $NF} 1' file
Default action 1 in the end will print all lines from input.

How to replace the empty place with next line content in shell script

1,n1,abcd,1234
2,n2,abrt,5666
,h2,yyyy,123x
3,h2,yyyy,123y
3,h2,yyyy,1234
,k1,yyyy,5234
4,22,yyyy,5234
the above given is my input file abc.txt , all I want the missing first column value should fill with next row first value.
example:
3,h2,yyyy,123x
3,h2,yyyy,123y
I want output like below,
1,n1,abcd,1234
2,n2,abrt,5666
3,h2,yyyy,123x// the missing first column value 3 should fill with second row first value
3,h2,yyyy,123y
3,h2,yyyy,1234
4,k1,yyyy,5234
4,22,yyyy,5234
How to implement this with help of AWK or some other alternate in shell script,please help.
Using awk you can do:
awk -F, '$1 ~ /^ *$/ {
p=p RS $0
next
}
p!="" {
gsub(RS " +", RS $1, p)
sub("^" RS, "", p)
print p
p=""
} 1' file
1,n1,abcd,1234
2,n2,abrt,5666
3,h2,yyyy,123x
3,h2,yyyy,123y
3,h2,yyyy,1234
4,k1,yyyy,5234
4,22,yyyy,5234
I would reverse the file, and then replace the value from the previous line:
tac filename | awk -F, '$1 ~ /^[[:blank:]]*$/ {$1 = prev} {print; prev=$1}' | tac
This will also fill in missing values on multiple lines.
With GNU sed:
$ sed '/^ ,/{N;s/ \(.*\n\)\([^,]*\)\(.*\)/\2\1\2\3/}' infile
1,n1,abcd,1234
2,n2,abrt,5666
3,h2,yyyy,123x
3,h2,yyyy,123y
3,h2,yyyy,1234
4,k1,yyyy,5234
4,22,yyyy,5234
The sed command does the following:
/^ ,/ { # If the line starts with 'space comma'
N # Append the next line
# Extract the value before the comma, prepend to first line
s/ \(.*\n\)\([^,]*\)\(.*\)/\2\1\2\3/
}
BSD sed would require an extra semicolon before the closing brace.
This only works with non-contiguous lines with missing values.

setting the output field separator in awk

I'n trying this statement in my awk script (in a file containing separate code, so not inline), script name: print-table.awk
BEGIN {FS = "\t";OFS = "," ; print "about to open the file"}
{print $0}
END {print "about to close stream" }
and running it this way from the shell
awk -f print-table.awk table
Where table is a tab separated file,
My goal is to declare the field separator (FS) and the output field separator (OFS) within the external function, and calling from the shell simply the
awk -f file input
without setting the field separator in the command line with -F"\t"
and without stdout it to a sed statement replacing the tab with a comma,
Any advise how can i do that?
You need to convince awk that something has changed to get it to reformat $0 using your OFS. The following works though there may be a more idiomatic way to do it.
BEGIN {FS = "\t";OFS = "," ; print "about to open the file"}
{$1=$1}1
END {print "about to close stream" }
You need to alter one of the field in awk:
awk 'BEGIN {FS="\t";OFS=","; print "about to open the file"} {$1=$1}1' file

Resources