Trying to use grep to find something, then output a different part of the line - linux

Say for instance I'm searching a line that is like this:
Color asdf
and I use grep to find that line, like grep asdf file.txt
How would I then display Color? Learning linux is hard.

With the command line tool sed you can replace stings by using regular expressions:
echo "Color asdf" | sed 's/\([^ ]*\).*/\1/'
This part: \([^ ]*\).* is a regular expresion. The first part of the regex: [^ ]*, matches any character except a space as many times as possible and what's between the \( and \) is being captured in the variable \1. Then you also match the remaining part of the string with .* and replace all of that with only the first word which was captured by \([^ ]*\) by using \1 in the replace part of the sed command.
Here some more info about sed:
http://linux.about.com/od/commands/a/Example-Uses-Of-Sed-Cmdsedxa.htm

You could use sed:
sed -n 's/[[:space:]][[:space:]]*asdf$//p' file.txt
Details:
The -n option tells sed not to print the pattern space automatically. Basically, it doesn't output anything unless you tell it to.
The s command of sed replaces text. Here, if a line ends with asdf, preceded by at least one whitespace character, we replace all of that with nothing and then print the line (notice the p flag at the end of the s command). The printing is only done if something was actually replaced. More information about the s command can be found e. g. in the GNU sed manual.
Edit for clarity: When using single quotes, parameter expansion does not work and thus, variables won't be replaced. To use variables, use double quotes:
search=asdf
sed -n "s/[[:space:]][[:space:]]*${search}\$//p" file.txt

If you'd really like to use grep here, you could pipe the output from grep into cut:
grep -h asdf *.txt | cut -s -d -f 1
Note that there have to be two spaces after the -d option to cut - the first tells cut to use a blank as the field delimiter (I'm assuming your fields are blank-delimited rather than tab-delimited), while the second separates the -d option from the following option (-f).
But, yeah, sed or awk are probably your friends here... :-)

you can color pattern in the line using grep
grep --colour -o 'asdf' file.txt
edit: the -o option will print only the patterns

Related

How to replace string into numbers using sed?

I am trying to replace string into number from the file
So, I have variable &FLOW which need to change to 001, ex :
cat file.txt
This is file ' PISP &FLOW'
PISD.DATA.CYCLE&FLOW..ONE
desired output
This is file ' PISP 001'
PISD.DATA.CYCLE001.ONE
I tried below commands in a script :
for item in file.txt
do
sed 's/\&FLOW/\./001/g' $item
sed 's/\&FLOW/001/g' $item
done
It is giving error. The second sed command is working, but I need to run first the beginning sed command otherwise after running first the second sed command, it would ignore the beginning sed command.
Any help would be appreciated!
Use a single sed command and use -i to actually modify the file contents and you need to pass file.txt as the input for the sed command:
sed -i 's/&FLOW\.\{0,1\}/001/g' file.txt
See the online demo. If you are using it in Mac OS, you need sed -i '' 's/&FLOW\.\{0,1\}/001/g' file.txt. Also see sed edit file in place.
Pattern details
It is a POSIX BRE compliant pattern matching
&FLOW - a literal &FLOW substring
\.\{0,1\} - 0 or 1 occurrence of a . char.
try this:
for item in file.txt
do
sed 's/\&FLOW\./001/g' $item
sed 's/\&FLOW/001/g' $item
done
You had a redundant / in after FLOW
This might also work:
sed -i 's/\&FLOW[\.]?/001/g' file.txt

Grep issues: Why is grep -i not grabbing the instance with special characters

I want to find this:
gxxcc/issdd/jaabb/krrss/lxxnn
On this (all capital letters)
AXXRR/BVVTTS/CRRTTDD/DEETTFF/EAABBRR/FRSSTT/GXXCC/ISSDD/JAABB_KRRSS_LXXNN/LL
I tried this
grep -i 'GXXCC/ISSDD/JAABB.KRRSS.LXXNN' filename.txt
grep -i 'GXXCC*ISSDD*JAABB*KRRSS*LXXNN' filename.txt
but, neither of those work. Any solution and explanation?
This, from your example, works fine, highlighting a portion of the text:
echo AXXRR/BVVTTS/CRRTTDD/DEETTFF/EAABBRR/FRSSTT/GXXCC/ISSDD/JAABB_KRRSS_LXXNN/LL |
egrep -i --color 'gxxcc/issdd/jaabb.krrss.lxxnn'
Avoid patterns like D*JAABB*K. That would match text like 'JAABBBBBBK' or 'DDDDDJAABK', rather than slashes or underscores.
The . dot matches exactly one character. Is your _ underscore maybe some crazy utf8 multibyte sequence, rather than ascii 95? One way to tell is to put Kleene stars in your pattern: egrep -i --color 'jaabb.*krrss.*lxxnn'. Another is to view your text with hexdump -C

sed command to replace newline character is not working in solaris but working in linux

I have following sed command working in linux box. but the same is not working in solaris box. Please correct me what the problem is ?
a=`sed ':a;N;$!ba;s/\n/ /g' file.txt`
Throws,
-bash-3.00$ a=`sed ':a;N;$!ba;s/\n/ /g' file.txt`
Label too long: :a;N;$!ba;s/\n/ /g
With sed on solaris you'll have to break it up like this:
sed -e ':a' -e 'N;$!ba' -e 's/\n/ /g' file.txt
According to man page:
b label Branch to the : command bearing the label.
If label is empty, branch to the end of
the script. Labels are recognized unique
up to eight characters.
Since they recognize up to eight characters, if your label is shorter than you'll need to split your sed in multiple expressions.
In the original sed, I think a label had to be on a line by itself. From my very ancient sed & awk Nutshell book, it states:
A lable is any sequence of up to seven character. A label is put on a line by itself and beginning with a colon:
:label
That means, you need to separate it from the rest of the script with multiple -e arguments or see if you have nawk or gawk on your Solaris box. Alternatively, since it appears you just want to replace all newlines with spaces, there are better tools for the job, such as tr, the translate utility, which should at least be as ubiquitous as sed:
a=`tr '\n' ' ' <file.txt`

grep - print all lines containing 'cat' as the second word

Ok so considering i have a file containing the following text:
lknsglkn cat lknrhlkn lsrhkn
cat lknerylnk lknaselk cat
awiooiyt lkndrhlk dhlknl
blabla cat cat bla bla
I need to use grep to print only the lines containing 'cat' as the second word on the line, namely lines 1 and 4. I've tried multiple grep -e 'regex' <file> commands but can't seem to get the right one. I don't know how to match the N'th word of a line.
this may work for you?
grep -E '^\w+\s+cat\s' file
if the first "word" can contain some non-word characters, e.g. "#, (,[..", you could also try:
grep -E '^\S+\s+cat\s' file
with your example input:
kent$ echo "lknsglkn cat lknrhlkn lsrhkn
cat lknerylnk lknaselk cat
awiooiyt lkndrhlk dhlknl
blabla cat cat bla bla"|grep -E '^\S+\s+cat\s'
lknsglkn cat lknrhlkn lsrhkn
blabla cat cat bla bla
What constitutes a word?
grep '^[a-z][a-z]* *cat '
This will work if there is at least a blank after cat. If that's not guaranteed, then:
grep -E '^[a-z]+ +cat( |$)'
which looks for cat followed by a blank or end of line.
If you want a more extensive definition of 'first word' (upper case, digits, punctuation), change the character class. If you want to allow for blanks or tabs, there are changes that can be made. If you can have leading blanks, add '*' at the caret. Variations as required.
These variations will work with any version of grep that supports the -E option. POSIX does not mandate notations such as \S to mean 'non-white-space', though GNU grep does support that as an extension. The grep -E version will work with regular egrep if grep -E does not work but egrep exists (don't use the -E option with egrep).
The following should work:
grep -e '^\S\+\scat\s'
The line should start with a non-whitespace of length at least 1, followed by a whitespace and the word "cat" followed by a whitespace.
Will be slower, but perhaps more readable:
awk '$2 == "cat"' file

How to remove a special character in a string in a file using linux commands

I need to remove the character : from a file. Ex: I have numbers in the following format:
b3:07:4d
I want them to be like:
b3074d
I am using the following command:
grep ':' source.txt | sed -e 's/://' > des.txt
I am new to Linux. The file is quite big & I want to make sure I'm using the write command.
You can do without the grep:
sed -e 's/://g' source.txt > des.txt
The -i option edits the file in place.
sed -i 's/://' source.txt
the first part isn't right as it'll completely omit lines which don't contain :
below is untested but should be right. The g at end of the regex is for global, means it should get them all.
sed -e 's/://g' source.txt > out.txt
updated to better syntax from Jon Lin's answer but you still want the /g I would think

Resources