Move lines matching a pattern from one file to another
This might work for you (GNU sed):
sed -i -e '/bar/{w file2' -e 'd}' file1
An alternative:
sed -i -e '/bar/w file2' -e '//d' file1
To append to file2, write to a temporary file and use cat to append at the end of file in a bash script, or use:
sed -i -e '/bar/w tmpfile' -e '$e cat tmpfile >> file2 && rm tmpfile' -e '//d' file1
N.B. For the last solution, only one input file can be modified at a time.
how to pick specific lines based on pattern match from a file to another file
Answer 1:
egrep -A 1 "Envvi|Department" example_1.txt | awk -F: -v ORS="-" '/Value/ {print tolower($2)}' | sed -e 's/[" ]//g' -e 's/-$/\n/' -e 's/^/aws_/'
Input: cat example_1.txt
{
"Key": "Envvi",
"Value": "model"
},
{
"Key": "Department",
"Value": "Sys"
}
{
"Key": "Subdept",
"Value": "io"
}
OutPut:
something_model-sys
Adding further explanation:
1) egrep -A 1 "Envvi|Department" example_1.txt --> This searches for the required key values and prints that line and one line after the match(-A 1). Output of this first step alone will be as follows:
"Key": "Envvi",
"Value": "model"
--
"Key": "Department",
"Value": "Sys"
2) awk -F: -v ORS="-" '/Value/ {print tolower($2)}' --> This finds the Value pair from previous output and prints the 2nd field, using ":" as field separator. tolower() is used for lower case output. Following is the output of this step. Note that there's no newline at the end as ORS is set to "-".
"model"- "sys"-
3) sed -e 's/[" ]//g' --> This part takes the input from previous step and removes any occurances of a double quotes and space. Following is the output after this step. Note that still there's no newline at the end.
model-sys-
4) 's/-$/\n/' --> This second part of sed takes the input from previous step and replaces the last occurance of hypen(-) at the end of the line with a newline. Following is the output after this step. Note that there's a newline now at the end.
model-sys
5) 's/^/aws_/' --> This final part of the sed takes the input from previous step and adds "aws_" string to the begining of the line.
aws_model-sys
Further improved/simplified version of Answer 1 that works in GNU AWK(using gsub):
egrep -A 1 "Envvi|Department" example_1.txt | awk -F: -v ORS="-" '/Value/ {gsub(/[" ]/,"",$2); print tolower($2)}' | sed -e 's/-$/\n/' -e 's/^/aws_/'
Moving matching lines in a text file using sed
While you ask a sed
solution I would propose to use awk
for this.
Using an ugly nesting of a multitude of sed
commands is not really recommended. Especially because you read your file twice.
Here is an awk
awk '/SRC_OUT_DIR/{t=$0;next}1;/DEFAULTS/{print t}' file
How does it work?
awk will read your file
line by line. Per line, it will do the following three commands one after the other:
/SRC_OUT_DIR/{t=$0;next}
: if the line contains a substring matchingSRC_OUT_DIR
, then store the line in a variablet
and move to thenext
line (don't execute 2 and 3)1
: default action: print the line/DEFAULTS/{print t}
: if the current line contains the substringDEFAULTS
, print the line stored in variablet
If you have multiple lines to move (this only moves downwards):
awk '/pattern1/ {t[1]=$0;next}
/pattern2/ {t[2]=$0;next}
/pattern3/ {t[3]=$0;next}
/target3/ { print t[3] }
1
/target1/ { print t[1] }
/target2/ { print t[2] }' file
note that pattern3
will be printed before target3
.
Move lines from one .txt file to another
Using findstr
you can print lines that don't match, too. So you can do it in several steps, psudocoded like this:
findstr pattern input > output
findstr /v pattern input > input-inverse
move /y input-inverse input
This should leave you with all lines matching pattern in output, and an input without those lines.
EDIT: Made the last step use move with an option to overwrite, so no need to remove the input before. I guess I (being mainly a Linux person) think of "rename" and "move" as the same thing, and took that overwrite for granted. So, thanks for the heads-up.
Print lines in one file matching patterns in another file
Try grep -Fwf file2 file1 > out
The -F
option specifies plain string matching, so should be faster without having to engage the regex engine.
How do I match a pattern and then copy multiple lines?
Your existing awk
matches correctly the rows from the ids' file, you now need to add a condition to print N lines ahead after reading the last field of the matching row. So we will set a variable p
to the number of lines to print plus one (the current one), and decrease per row printing.
awk -F'/' 'NR==FNR{id[$0]; next} $1 in id{p=$6+1} p-->0{print}' file1 file2
or the same with last condition more "awkish" (by Ed Morton) and covering any possible extreme case of a huge file
awk -F'/' 'NR==FNR{id[$0]; next} $1 in id{p=$6+1} p&&p--' file1 file2
here the print
condition is omitted, as it is the default action, and the condition is true again as long as decreasing p
is positive.
Related Topics
Angular Cli App Not Running When Deploying to Linux App Service
Substituting a String in Place of Variable in Shell
Replace System Call in Linux Kernel 3
Can't Register a Snapshot Repository in Elasticsearch
Self Updating Bash Script from Github
Can't Access Publicly Exposed Docker Container Port from External Machine, Only from Localhost
Gnu Time and Formatting Output
Extract Lines When Column K Is Empty with Awk/Perl
How to Disable Non-Breaking Space with Altgr+Space
(13)Permission Denied: Access to /Cgi-Bin/Test.Cgi Denied
How to Use Source Command Within Jenkins Pipeline Script
Is Wget or Similar Programs Always Available on Posix Systems
Difference Between a Stripped Binary and a Non Stripped Binary in Linux
Cx_Oracle: Distutils.Errors.Distutilssetuperror: Cannot Locate Oracle Include Files
How to Store Output from Printf with Formatting in a Variable