awk or sed replacing specific $3 with ajacent $2 - sed

File looks like
$1 $2 $3
Text Text2 *
Text Text4 Text3
I would like to search for *'s within a file and replace the with the text in the column next to it. While keeping the rest of the info... basicly replace the * logicaly with column 2.
Currently I am working with either sed or awk
awk : awk '{ if($3=*) {print$2}}' works... but I would like to keep $1,2 aswell
sed : sed -r 's/[*]//g' I can't get reg expression to replace with $2 properly
Any quick help, tips or tricks?

Contents of file.txt:
Text Text2 *
Text Text4 Text3
One way using awk:
awk '$3 == "*" { $3=$2 }1' file.txt
Results:
Text Text2 Text2
Text Text4 Text3

With GNU sed \S and \s can be used to represent non-space and space respectively, so you could accomplish what you want like this:
sed -r '/(\S+)\s+(\S+)\s+\*/ s//\1 \2 \2/'
The empty s/// command implicitly uses the matches from //.
If it is run on the input listed by steve:
sed -r '/(\S+)\s+(\S+)\s+\*/ s//\1 \2 \2/' file.txt
Output:
Text Text2 Text2
Text Text4 Text3
If you want to preserve inter-column whitespace use:
sed -r '/(\S+)(\s+)(\S+)(\s+)\*/ s//\1\2\3\4\3/'

awk solution:
awk '$3=="*"{$3=$2}1' file

Related

Extract substrings between strings

I have a file with text as follows:
###interest1 moreinterest1### sometext ###interest2###
not-interesting-line
sometext ###interest3###
sometext ###interest4### sometext othertext ###interest5### sometext ###interest6###
I want to extract all strings between ### .
My desired output would be something like this:
interest1 moreinterest1
interest2
interest3
interest4
interest5
interest6
I have tried the following:
grep '###' file.txt | sed -e 's/.*###\(.*\)###.*/\1/g'
This almost works but only seems to grab the first instance per line, so the first line in my output only grabs
interest1 moreinterest1
rather than
interest1 moreinterest1
interest2
Here is a single awk command to achieve this that makes ### field separator and prints each even numbered field:
awk -F '###' '{for (i=2; i<NF; i+=2) print $i}' file
interest1 moreinterest1
interest2
interest3
interest4
interest5
interest6
Here is an alternative grep + sed solution:
grep -oE '###[^#]*###' file | sed -E 's/^###|###$//g'
This assumes there are no # characters in between ### markers.
With GNU awk for multi-char RS:
$ awk -v RS='###' '!(NR%2)' file
interest1 moreinterest1
interest2
interest3
interest4
interest5
interest6
You can use pcregrep:
pcregrep -o1 '###(.*?)###' file
The regex - ###(.*?)### - matches ###, then captures into Group 1 any zero o more chars other than line break chars, as few as possible, and ### then matches ###.
o1 option will output Group 1 value only.
See the regex demo online.
sed 't x
s/###/\
/;D; :x
s//\
/;t y
D;:y
P;D' file
Replacing "###" with newline, D, then conditionally branching to P if a second replacement of "###" is successful.
This might work for you (GNU sed):
sed -n 's/###/\n/g;/[^\n]*\n/{s///;P;D}' file
Replace all occurrences of ###'s by newlines.
If a line contains a newline, remove any characters before and including the first newline, print the details up to and including the following newline, delete those details and repeat.

SED Insert text after a specific multi-line text field

I am looking to search for and add a new line of text after a specific multi-line text, in this example i need to add a space and text after "oldText" under "[old-text]" only:
[old-text]
oldText
[inserted-new-text]
newTxt
[alsoOld-text]
oldText
Here's what I have so far but the syntax is not correct:
printf "[old-text]\noldText"|sed '/\[old-text]\noldTex\t/a [inserted-new-text]\nnewTxt'
$ sed -e '/\[old-text\]/{N;s/oldText/&\n\n[inserted-new-text]\nnewTxt/}' inputFile
Use /<pattern>/ to find the [old-text] and then use N; to go to the next line and replace.
$ printf "[old-text]\noldText" | \
sed -e '/\[old-text\]/{N;s/oldText/&\n\n[inserted-new-text]\nnewTxt/}'
[old-text]
oldText
[inserted-new-text]
newTxt

delete string for each line with sed

My file contains x number of lines, I would like to remove the string before and after the reference string at the beginning and end of each line.
The reference string and string to remove are separated by space.
The file contains :
test.user.passs
test.user.location
global.user
test.user.tel
global.pass
test.user.email string_err
#ttt...> test.user.car ->
test.user.address
è_ 788 test.user.housse
test.user.child
{kl78>&é} global.email
global.foo
test.user.foo
How to remove the string at the start of each line which contain "test" string and also the end of each line separated by space or tab with sed?
The desired result is :
test.user.passs
test.user.location
global.user
test.user.tel
global.pass
test.user.email
test.user.car
test.user.address
test.user.housse
test.user.child
{kl78>&é} global.email
global.foo
test.user.foo
I interpret your question as: find the first word that is "word characters and at least one dots"
Tcl:
echo '
set fh [open [lindex $argv 1] r]
while {[gets $fh line] != -1} {puts [regexp -inline {\w+(?:\.\w+)+} $line]}
' | tclsh - file
sed
sed -r 's/.*\<([[:alpha:]]+(\.[[:alpha:]]+)).*/\1/' file
perl
perl -nE '/(\w+(\.\w+)+)/ and say $1' file
using sed like
sed -r 's/^[^ ]+[ ]+([^ ]+)[ ]+[^ ]*/\1/' file
This might work for you (GNU sed):
sed -r 's/.*(test\S+).*/\1/' file

SED append on next n-th line, not append to next line

How can I get sed to append sometext two line after it find a match?
For example:
text0
text1
text2
text3
after I match text0, I want to append text4 after the next 2 line, that is:
text0
text1
text2
text4
text3
I'd say:
sed -e '/text0/ { N; N; a text4' -e '}' filename
That is:
/text0/ { # when finding a line that matches text0
N # fetch two more lines
N
# and only then append text4
a text4
}
When using this as a one-liner, it is necessary to split it into two -e options so that the a command doesn't attempt to append a line text4 }.
Alternatively, you could use
sed '/text0/ { N; N; s/$/\ntext4/; }' filename
this avoids using the somewhat unwieldy a command but requires you to escape some metacharacters in the replacement text (such as \ and &).
Perl solution:
perl -pe 'push #append, 3 + $. if /text0/;
shift #append, print "text4\n" if $append[0] == $.;
' input.txt > output.txt
You might need some more tweaking if the string is to be appended after the end of the input.
Explanation:
$. is the line number.
when /text0/ is matched, the line number where the append should happen is pushed into the array #append.
when the current line number corresponds to the one at the beginning of the array, the line is printed and the first element of the array is discarded.
It also means it works for overlapping matches and appends.
I would have used awk for this:
awk '/text0/ {f=NR} f && NR==f+2 {$0=$0RS"text4"}1' file
text0
text1
text2
text4
text3
When pattern is found, set f to current line number.
When f is true and two lines later f && NR==f+2 add new text $0=$0RS"text4".
1 print the result

Sed help requred

I like to find some thing with sed in file that have many occurrence
File As below
"xyz": "somename_dsa", some other text, "xyz": "zcbr53", some other text, "xyz": "zms53",
Item needed
I need text after "xyz" :
Using gnu awk
awk -v RS='"xyz"' 'NR>1 {print $2}' file
"somename_dsa",
"zcbr53",
"zms53",
Or just the data
awk -v RS='"xyz"' -F\" 'NR>1 {print $2}' file
somename_dsa
zcbr53
zms53
This might work for you (GNU sed):
sed '/"xyz":\s*/!d;s//\n/g;s/^[^\n]*\n//' file
Delete any lines that don't have the required string. Replace the required string with a newline and chop off the first entry.
You may try this,
$ cat rr.txt
"xyz": "somename_dsa", some other text, "xyz": "zcbr53", some other text, "xyz": "zms53"
$ sed -r '/[^"]*"xyz": ([^,]*)/ s//\1 /g' rr.txt
"somename_dsa" "zcbr53" "zms53"
$ sed -r '/[^"]*"xyz": "([^"]*)"/ s//\1 /g' rr.txt
somename_dsa zcbr53 zms53
All the captured texts are separated by spaces.