Remove a Dynamic Suffix Pattern from String in Unix Shell Scripting - linux

I have data in the format below:
2.7G58%/usr
8%/oravl02
49%/oravl01
98%/osszoneusr/osszone/user
and I need to remove everything from beginning of the line to the percentage so that the output of above sample data would be:
/usr
/oravl02
/oravl01
/osszoneusr/osszone/user
I am specifically looking for linux in-built string striping or sed as in solution.

Using awk:
awk -F '%' '{print $2}' file
Using sed:
sed -i.bak 's/^.*%//' file
Using cut:
cut -d% -f2 file

An awk variation.
awk -F% '$0=$NF' file
/usr
/oravl02
/oravl01
/osszoneusr/osszone/user

Please try in below ways
cut: the delimiter must be a single character
bcsmc2rtese001 [~/Shell_p]$ cut -d '%' -f2 text1.txt
/usr
/oravl02
/oravl01
bcsmc2rtese001 [~/Shell_p]$ awk -F "%" '{print $2}' text1.txt
/usr
/oravl02
/oravl01
/osszoneusr/osszone/user

Related

How do you change column names to lowercase with linux and store the file as it is?

I am trying to change the column names to lowercase in a csv file. I found the code to do that online but I dont know how to replace the old column names(uppercase) with new column names(lowercase) in the original file. I did something like this:
$cat head -n1 xxx.csv | tr "[A-Z]" "[a-z]"
But it simply just prints out the column names in lowercase, which is not enough for me.
I tried to add sed -i but it did not do any good. Thanks!!
Using awk (readability winner) :
concise way:
awk 'NR==1{print tolower($0);next}1' file.csv
or using ternary operator:
awk '{print (NR==1) ? tolower($0): $0}' file.csv
or using if/else statements:
awk '{if (NR==1) {print tolower($0)} else {print $0}}' file.csv
To change the file for real:
awk 'NR==1{print tolower($0);next}1' file.csv | tee /tmp/temp
mv /tmp/temp file.csv
For your information, sed using the in place edit switch -i do the same: it use a temporary file under the hood.
You can check this by using :
strace -f -s 800 sed -i'' '...' file
Using perl:
perl -i -pe '$_=lc() if $.==1' file.csv
It replace the file on the fly with -i switch
You can use sed to tell it to replace the first line with all lower-case and then print the rest as-is:
sed '1s/.*/\L&/' ./xxx.csv
Redirect the output or use -i to do an in-place edit.
Proof of Concept
$ echo -e "COL1,COL2,COL3\nFoO,bAr,baZ" | sed '1s/.*/\L&/'
col1,col2,col3
FoO,bAr,baZ

Search A and replace B in A|B in shell scripting/SED/AWK

I have a text file with layout as:
tableName1|counterVariable1
tableName2|counterVariable2
I want to replace the counterVariable1 with some other variable say counterVariableNew.
How can I accomplish this?
I have tried various SED/AWK approaches, closest one is mentioned below:
cat $fileName | grep -w $tableName | sed -i 's/$tableName\|counterVariable/$tableName\|counterVariableNew'
But all the 3 commands are not merging properly, please help!
Your script is an example of [ useless use of cat ]. But the key point here is to escape the pipe delimiter which has a special meaning(it stands for OR) when used with awk FS. So below script should do
# cat 42000479
tableName1|counterVariable1
tableName2|counterVariable2
tableName3|counterVariable2
# awk -F\| '$1=="tableName2"{$2="counterVariableNew"}1' 42000479
tableName1|counterVariable1
tableName2 counterVariableNew
tableName3|counterVariable2
An alternate way of doing the same stuff is below
# awk -v FS='|' '$1=="tableName2"{$2="counterVariableNew"}1' 42000479
Stuff inside the single quote will not be expanded.
awk -F'|' -v OFS='|' '/tableName1/ {$2="counterVariableNew"}1' file
tableName1|counterVariableNew
tableName2|counterVariable2
This will search for A (tableName1) and replace B (counterVariable1) to counterVariableNew.
Or by using sed :
sed -r '/tableName1/ s/(^.*\|)(.*)/\1counterVariableNew/g' file
tableName1|counterVariableNew
tableName2|counterVariable2
For word bounded search: Enclose the pattern inside \< and \> .
sed -r '/\<tableName1\>/ s/(^.*\|)(.*)/\1counterVariableNew/g' file
awk -F'|' -v OFS='|' '/\<tableName1\>/ {$2="counterVariableNew"}1' file

How to replace one or more consecutive symbols with one symbol in shell

I have a file containing consecutive symbols (as pipe "|") like
ANKRD54,LIAR,allergy,|||
ANKRD54,LIAR,asthma,||20447076||
ANKRD54,LIAR,autism,||||
ANKRD54,LIAR,cancer,|||
ANKRD54,LIAR,chronic_obstructive_pulmonary_disease,|||
ANKRD54,LIAR,dental_caries,||||
Now using shell or a sed command in shell is it possible to replace multiple pipe with one pipe like
ANKRD54,LIAR,allergy,|
ANKRD54,LIAR,asthma,|20447076|
ANKRD54,LIAR,autism,|
ANKRD54,LIAR,cancer,|
ANKRD54,LIAR,chronic_obstructive_pulmonary_disease,|
ANKRD54,LIAR,dental_caries,|
I guess the easiest way is use built-in commands: cat your_file | tr -s '|'
Pass your text to sed (e.g. via a pipe)
cat your_file | sed "s/|\+/|/g"
You can do that with a simple awk gsub as:-
awk -F"," -v OFS="," '{gsub(/[|]+/,"|",$4)}1' file
See it in action:-
$ cat file
ANKRD54,LIAR,allergy,|||
ANKRD54,LIAR,asthma,||20447076||
ANKRD54,LIAR,autism,||||
ANKRD54,LIAR,cancer,|||
ANKRD54,LIAR,chronic_obstructive_pulmonary_disease,|||
ANKRD54,LIAR,dental_caries,||||
$ awk -F"," -v OFS="," '{gsub(/[|]+/,"|",$4)}1' file
NKRD54,LIAR,allergy,|
ANKRD54,LIAR,asthma,|20447076|
ANKRD54,LIAR,autism,|
ANKRD54,LIAR,cancer,|
ANKRD54,LIAR,chronic_obstructive_pulmonary_disease,|
ANKRD54,LIAR,dental_caries,|

Linux sed, how to delete the rest of the word?

Suppose I have text.txt:
342423423423 - 'namefile.jpg' saved (2423423kb/2423423kb)
I can use
sed 's/^.*- //' text.txt
the output will be:
'namefile.jpg' saved (2423423kb/2423423kb)
it will get rid the text at the beginning of that namefile.jpg, but what if I also want to get rid the rest of it ? I want the output to be like this:
'namefile.jpg'
What sed pattern should I use? Please note that after the 'namefile.jpg' the text isn't always the same. It changes from time to time.
You could use capturing groups.
sed 's/^.*- \([^ ]\+\).*/\1/' text.txt
OR
sed 's/^.*- //;s/ .*//' file
^.*- regex matches all the characters from the start upto -. And the first command replaces all the matches characters with an empty string.
.* Now from the resultant string, this regex would match all the characters from the first space upto the last. Replacing those characters with an empty string will gave you the desired output.
Example:
$ echo "342423423423 - 'namefile.jpg' saved (2423423kb/2423423kb" | sed 's/^.*- \([^ ]\+\).*/\1/'
'namefile.jpg'
$ echo "342423423423 - 'namefile.jpg' saved (2423423kb/2423423kb" | sed 's/^.*- //;s/ .*//'
'namefile.jpg'
Or with awk:
echo "342423423423 - 'namefile.jpg' saved (2423423kb/2423423kb)" | awk '{print $3}'
Default delimiter for awk is space. Just print the 3rd field.
Try this way also
sed "s/.*\('.*'\).*/\1/" FileName
Output :
'namefile.jpg'
This is not sed but show how to do it with awk
awk -F\' '{print $2}' text.txt
namefile.jpg
or if you like to have the single quotes.
awk -F\' '{print FS$2FS}' text.txt
'namefile.jpg'
Just use a simple cut command
cut -d ' ' -f3 text.txt
or you can also use this,
sed 's/^.*- //' text.txt|cut -d ' ' -f1
Both will give you this Output:
'namefile.jpg'

How to reverse order of fields using AWK?

I have a file with the following layout:
123,01-08-2006
124,01-09-2007
125,01-10-2009
126,01-12-2010
How can I convert it into the following by using AWK?
123,2006-08-01
124,2007-09-01
125,2009-10-01
126,2009-12-01
Didn't read the question properly the first time. You need a field separator that can be either a dash or a comma. Once you have that you can use the dash as an output field separator (as it's the most common) and fake the comma using concatenation:
awk -F',|-' 'OFS="-" {print $1 "," $4,$3,$2}' file
Pure awk
awk -F"," '{ n=split($2,b,"-");$2=b[3]"-"b[2]"-"b[1];$i=$1","$2 } 1' file
sed
sed -r 's/(^.[^,]*,)([0-9]{2})-([0-9]{2})-([0-9]{4})/\1\4-\3-\2/' file
sed 's/\(^.[^,]*,\)\([0-9][0-9]\)-\([0-9][0-9]\)-\([0-9]\+\)/\1\4-\3-\2/' file
Bash
#!/bin/bash
while IFS="," read -r a b
do
IFS="-"
set -- $b
echo "$a,$3-$2-$1"
done <"file"
Unfortunately, I think standard awk only allows one field separator character so you'll have to pre-process the data. You can do this with tr but if you really want an awk-only solution, use:
pax> echo '123,01-08-2006
124,01-09-2007
125,01-10-2009
126,01-12-2010' | awk -F, '{print $1"-"$2}' | awk -F- '{print $1","$4"-"$3"-"$2}'
This outputs:
123,2006-08-01
124,2007-09-01
125,2009-10-01
126,2010-12-01
as desired.
The first awk changes the , characters to - so that you have four fields separated with the same character (this is the bit I'd usually use tr ',' '-' for).
The second awk prints them out in the order you specified, correcting the field separators at the same time.
If you're using an awk implementation that allows multiple FS characters, you can use something like:
gawk -F ',|-' '{print $1","$4"-"$3"-"$2}'
If it doesn't need to be awk, you could use Perl too:
$ perl -nle 'print "$1,$4-$3-$2" while (/(\d{3}),(\d{2})-(\d{2})-(\d{4})\s*/g)' < file.txt

Resources