Round numbers and divide them to 2 columns - sed

Now it looks like:
xmin = 0
xmax = 15.393970521541949
xmin = 15.393970521541949
xmax = 27.58997052154195
xmin = 27.58997052154195
xmax = 46.05797052154195
xmin = 46.05797052154195
xmax = 65.67797052154194
xmin = 65.67797052154194
xmax = 81.08048969617173
xmin = 81.08048969617173
xmax = 82.7959410430839
It should look like:
0 15.39
15.39 27.59
27.59 46.06
46.06 65.68
.
.
.
Hi I have .txt file from which I filtered only this xmin, xmax numbers with command:
sed -n '16,$p' info.txt | grep "xmin\|xmax"
I know how to show only numbers but I don't know how to round this numbers and divide them into 2 columns. The result should look like the example.

awk could do it easily:
awk '{printf "%.2f%s",$3,!(NR%2)?"\n":FS}' file
with your example:
kent$ cat f
xmin = 0
xmax = 15.393970521541949
xmin = 15.393970521541949
xmax = 27.58997052154195
xmin = 27.58997052154195
xmax = 46.05797052154195
xmin = 46.05797052154195
xmax = 65.67797052154194
xmin = 65.67797052154194
xmax = 81.08048969617173
xmin = 81.08048969617173
xmax = 82.7959410430839
kent$ awk '{printf "%.2f%s",$3,!(NR%2)?"\n":FS}' f
0.00 15.39
15.39 27.59
27.59 46.06
46.06 65.68
65.68 81.08
81.08 82.80

awk '{printf("%.2f ", $NF)} !(NR%2){printf("\n")}' File
Print the last field ($NF) in each line with format specifier (%.2f). Print newline after every second line.

my $mi,$ma;
while (<>) {
if (/xmin = ([0-9.]*)/) { $mi=sprintf("%.2f", $1); next; };
if (/xmax = ([0-9.]*)/) { $ma=sprintf("%.2f", $1); printf "$mi $ma\n" };
}
running this perl script with:
script.pl < data
would result in
0.00 15.39
15.39 27.59
27.59 46.06
46.06 65.68
65.68 81.08
81.08 82.80

sed 'N;s/xm.. = //g;s/\([0-9]*\.[0-9]\{2\}\)[0-9]*/\1/g;y/\n/ /' info.txt
read 2 lines
remove the xman/xmin =
trunc the number
change new line to space
cycle
(POSIX version so --posix for GNU sed)

Related

Fixed size output data in MATLAB

I am trying to have a matrix which its elements doesn't have the same size .
Say the element_1 = 0.1234567 and the element_2 = 0.1 and I need the element_2 =0.1000000 so that both of them has the same size.
clc;clear all
a = rand(4,12);
COL_Names ={'This_is_Colu_No_1','This_is_Colu_No_2','This_is_Colu_No_3','This_is_Colu_No_4','This_is_Colu_No_5','This_is_Colu_No_6','This_is_Colu_No_7','This_is_Colu_No_8','This_is_Colu_No_9','This_is_Colu_No_10','This_is_Colu_No_11','This_is_Colu_No_12'};
rowNames = {'ROW1';'ROW2';'ROW3';'ROW4'};
T = array2table(a,'VariableNames',COL_Names,'RowNames',rowNames);
writetable(T,'Data.txt','Delimiter','\t','WriteRowNames',true);
type Data.txt ;
The OutPut is like this
Row This_is_Colu_No_1 This_is_Colu_No_2 This_is_Colu_No_3 This_is_Colu_No_4 This_is_Colu_No_5 This_is_Colu_No_6 This_is_Colu_No_7 This_is_Colu_No_8 This_is_Colu_No_9 This_is_Colu_No_10 This_is_Colu_No_11 This_is_Colu_No_12
ROW1 0.139740979774291 0.231035232035157 0.347778782863186 0.279682446566279 0.060995054119542 0.233212699943628 0.507599581908539 0.833087779293817 0.552819386888535 0.43251811668393 0.342580158122272 0.420574544492339
ROW2 0.00459708931895875 0.703626845695885 0.33064632159971 0.85782393462353 0 0.935097755896966 0.582441521353621 0.155241648807001 0.163717355897126 0.48985529896707 0.0134551766978835 0.810989133317225
ROW3 0.791254563282513 0.650747335567064 0.293769172888192 0.15110222627643 0.962791661993452 0.842147123142386 0.586462512126695 0.109349751268813 1 0.00525695361457879 0.700826048054212 0.989915984093474
ROW4 0.513993416249574 0.868158891144176 0.293769172888 0.552496163682282 0.301098948730568 0.779790450269442 0.420527994140777 0.523231514251179 0.0602548802340035 0.261436547849062 0.84923648156472 0.433189006269314
I think you need to do it manually using fprintf with formatSpec:
clc, clear, rng(3);
a = rand(4, 3);
colNames = {'This_is_Colu_No_9', 'This_is_Colu_No_10', 'This_is_Colu_No_11'};
rowNames = {'ROW98'; 'ROW99'; 'ROW100'; 'ROW101'};
formatSpecHead = '%-6s %-22s %-22s %-22s\n';
formatSpecRow = '%-6s %.20f %.20f %.20f\n';
fid = fopen('a.fwf', 'w');
fprintf(fid, formatSpecHead, 'Row', colNames{:}); % write header
for row = 1:size(a, 1)
fprintf(fid, formatSpecRow, rowNames{row}, a(row, :)); % write row
end
fclose(fid);
Then a.fwf looks like:
Row This_is_Colu_No_9 This_is_Colu_No_10 This_is_Colu_No_11
ROW98 0.55079790257457550418 0.89294695434765469777 0.05146720330082987793
ROW99 0.70814782261810482744 0.89629308893343806464 0.44080984365063646813
ROW100 0.29090473891294432729 0.12558531046383625274 0.02987621087856695556
ROW101 0.51082760519766301499 0.20724287813818675907 0.45683322439471107934

Multiply ffprobe fps as value in powershell

I'm trying to print the multiplied fps of a video with ffprobe,
.\ffprobe.exe -v error -select_streams v -of default=noprint_wrappers=1:nokey=1 -show_entries stream=avg_frame_rate -i "$videopath" > rate 2>&1
$script:rate = [IO.File]::ReadAllText(".\rate")
$script:framerate = ($rate/2)
echo "Multiplied = "$framerate
What this is supposed to do is to write the fps into a file, which ffprobe does as a fraction (1/10 in this case), and then multiply it by 2.
Since the variable is read as literal text I can't multiply it by 2, and instead it just gives me this.
Multiplied =
1/10
1/10
Is there any way to make it print Multiplied = 20 instead
Powershell doesn't understand fractions, so you'll need to convert the string into numbers and then do the math.
$rate = "1/10";
# convert the string into numbers
$parts = $rate.Split("/"); # #( "1", "10")
$numerator = [int] $parts[0]; # 1
$denominator = [int] $parts[1]; # 10
# do the math
$framerate = $denominator * 2; # 20
write-host "Multiplied = $framerate"
# Multiplied = 20

How can I remove <math></math> multiline sections with Perl?

How can I remove multiline sections with Perl?
I have such wiki test code:
{|
|-
| colspan="2"|
: <math>
[\underbrace{\color{Red}4,2}_{4 > 2},5,1,7] \rightarrow
[2,\underbrace{\color{OliveGreen}4,5}_{4 < 5},1,7] \rightarrow
[2,4,\underbrace{\color{Red}5,1}_{5 > 1},7] \rightarrow
[2,4,1,\underbrace{\color{OliveGreen}5,7}_{5 < 7}]
</math>
|-
|
: <math>
[\underbrace{\color{OliveGreen}2,4}_{2 < 4},1,5,{\color{Blue}7}] \rightarrow
[2,\underbrace{\color{Red}4,1}_{4 > 1},5,{\color{Blue}7}] \rightarrow
[2,1,\underbrace{\color{OliveGreen}4,5}_{4 < 5},{\color{Blue}7}]
</math>
: <math>
[\underbrace{\color{Red}2,1}_{2 > 1},4,{\color{Blue}5},{\color{Blue}7}] \rightarrow
[1,\underbrace{\color{OliveGreen}2,4}_{2 < 4},{\color{Blue}5},{\color{Blue}7}]
</math>
: <math>
[\underbrace{\color{OliveGreen}1,2}_{1 < 2},{\color{Blue}4},{\color{Blue}5},{\color{Blue}7}]
</math>
|}
And I want to remove from this code all how to do it? I have done such code:
cat math-text.txt | perl -e 'while(<>) { s/<math>.+?<\/math>//gs; print $_; }'
It is not works but should since documentation explains that . will much new lines. How to do it?
The following is a python script which I use to extract all the mathematical formula from wikipedia dumps. Rather than using a multi-line regexp it scans for occurrences of <math> </math> and uses the position on the line to work out where the actual position on the line is and uses a finite state machine to find the actual equations, basically with two states determined by inEqn. It does a few other things like find the title and name space and attributes in the maths tags.
As dumps are in the order of 100MB using a line by line approach may well end up being more efficient than multi-line regexps.
import sys
import re
titleRE = re.compile('<title>(.*)</title>')
nsRE = re.compile('<ns>(.*)</ns>')
mathRE = re.compile('</?math(.*?)>')
pageEndRE = re.compile('</page>')
title =""
attr = ""
ns = -1
inEqn = 0
for line in sys.stdin:
m = titleRE.search(line)
if m :
title = m.group(1)
expression = ""
inEqn = 0
m = nsRE.search(line)
if m :
ns = m.group(1)
start = 0
pos = 0
m = mathRE.search(line,pos)
while m :
if m.group().startswith('<math'):
attr = m.group(1)
start = m.end()
pos = start
expression = ""
inEqn = 1
if m.group() == '</math>' :
end = m.start()
expression = ' '.join([expression,line[start:end]])
print title,'\t',attr,'\t',expression.lstrip().replace('<','<').replace('>','>').replace('&','&')
pos = m.end()
expression = ""
start = 0
inEqn = 0
m = mathRE.search(line,pos)
if start > 0 :
expression = line[start:].rstrip()
elif inEqn :
expression = ' '.join([expression,line.rstrip()])
Another option might be to consider an xml parser. A SAX or DOM based parser would be able to find the equations. This might be worth considering if you want to do more sophisticated analysis of the wiki-text.

Change a number arithmetically in a text file using perl

I have a bunch of numbers in a text file as follows (example
r0 = 204
r1 = 205
max_gap = 20u
min = 0
max = 8
thickness = 2
color = green
fill_under = yes
fill_color = green
r0 = 205
r1 = 206
I would like to divide any line with r0 = by 100 so that the line will then read
r0 = 20.4
I would like to do this for all lines with r0 and also for r1. Is there a way to do this in perl?
This is my attempt but doesnt work mainly because I've never used perl before which is why I'm asking such a simple question
#!/usr/bin/perl
$string= r0\s+=\s+\\(d+)
$num= $1/100
$num2= r0\s+=\s+\\$num
s/$string/$num2;
A one liner I could run from bash would be much better though. I know it'll involve the s/find/replace function but not sure how to specify the integer part
perl -pei 's#^(r[01]\s*=\s*)(\d+)$#$1.$2/100#e' filename
The options mean:
-p = Run the code in a loop that prints the modified input
-e = Execute the code in the first argument
-i = Replace the input file(s) with the output
The regular expression bits mean:
^ = beginning of line
r[01] = r0 or r1
\s*=\s* = any amount of whitespace, an =, and any amount of whitespace
\d+ = digits
$ = end of line
The replacement uses the e modifier, which means that it should be executed as a Perl expression. $1 and $2 are the contents of the two capture groups: $1 is everything before the number, $2 is the number. $2/100 divides the number by 100, and . concatenates the two pieces together.
As a one-liner:
perl -pi -e 's{^r[01]\s*=\s*\K(\d+)$}{$1/10}e' filename.txt
Here is an awk solution:
awk '/^r[01]/ {$3/=100} 1' file
r0 = 2.04
r1 = 2.05
max_gap = 20u
min = 0
max = 8
thickness = 2
color = green
fill_under = yes
fill_color = green
r0 = 2.05
r1 = 2.06

If statement inside awk to change a value

I have the following file
...
MODE P E
IMP:P 1 19r 0
IMP:E 1 19r 0
...
SDEF POS= 0 0 14.6 AXS= 0 0 1 EXT=d3 RAD= d4 cell=23 ERG=d1 PAR=2
SI1 L 0.020
SP1 1
SI4 0. 3.401
SI3 0.9
...
NPS 20000000
I want to do the following task
Check if after the sequence ERG= there is a number or a string.
If it's a string, find the sequence SI1 L and change the value after that, using values that the user inputs.
If it's a number, change the number using values that the user inputs.
Note that if after ERG= there is a number, there will be no SI1 L sequence.
For instance number 2 can be accomplished using the following
#! /bin/bash
vals=(0.02 0.03 0.04 0.05)
for val in "${vals[#]}"; do
awk -vval="$val" '$1=="SI1"{$3=val}1' 20
done
How can the above algorithm be achieved?
#!/bin/bash
val="$#"
awk -v val="$val" '
BEGIN { i=1; split (val,v," ") }
# If it is a string, find the sequence SI1 L and change the value after that, using values that the user inputs
/SDEF POS.*ERG=[a-zA-Z]+/ { flag="y" ; }
/SI1 L/ { if (flag=="y") { $3=v[i]; i++; flag="n"; } }
# If it is a number, change the number using values that the user inputs.
/SDEF POS.*ERG=[0-9]+ / { sub(/ERG=[0-9]*/, "ERG="v[i],$0);i++; }
1
' file
hints:
If the rule find ERG with at least one or more letters ([a-zA-Z]+, it will set the flag.
The /SI1 L/ rule will only triggers, if the flag is set. If the rule triggered, it would unset the flag again, so that any following /SI L/ wouldn't trigger again.
.* stands for 0-n sign or character
[A-Za-z]+ stands for 1-n alphabetic character in lower or upper case
awk -F '[[:blank:]=]' -v string_value="foo" -v number_value=42 '
/ERG=/ {
for (i=1; i<NF; i++)
if ($i == "ERG") {
isstring = ($(i+1) ~ /[^[:digit:]]/)
break
}
if (!isstring)
$(i+1) = number_value
}
/SI1 L/ && isstring { $NF = string_value }
1
' filename