I have a file of the following format:
abc: A B C D E
abc: 1 2 3 4 5
def D E F G H
def: 10 11 12 23 99
...
That is a first line with strings after ':' is a header for the next line with numbers. I'd like to use sed to extract only a line starting with PATTERN string with numbers in the line.
Number of numbers in a line is variable, but assume that I know exactly how many I'm expecting, so I tried this command:
% sed 's/^abc: \([0-9]+ [0-9]+ [0-9]+\)$/\1/g' < file.txt
But it dumps all entries from the file. What am I doing wrong?
sed does substitutions and prints each line, whether a substitution happens or not.
Your regular expression is wrong. It would match only three numbers separated by spaces if extended regex flag was given (-E). Without it, not even that, because the + sign will be interpreted literally.
The best here is to use addresses and only print lines that have a match:
sed -nE '/^abc: [0-9]+ [0-9]+ [0-9]+ [0-9]+ [0-9]+$/p' < file.txt
or better,
sed -nE '/^abc:( [0-9]+){5}$/p' < file.txt
The -n flag disables the "print all lines" behavior of sed described in (1). Only the lines that reach the p command will be printed.
to extract only a line starting with PATTERN string with numbers in the line and Number of numbers in a line is variable means at least one number, so:
$ sed -n '/abc: \([0-9]\+\)/p' file
Output:
abc: 1 2 3 4 5
With exactly 5 numbers, use:
$ sed -n '/abc: \([0-9]\+\( \|$\)\)\{5\}/p' file
With #Mark's additional question in a comment "If I want to just extract the matched numbers (and remove prefix, e.g, abc)…" this is the pattern I came up with:
sed -En 's/^abc: (([0-9]+[ \t]?)+)[ \t]*$/\1/gp' file.txt
I'm using the -E flag for extended regular expressions to avoid all the escaping that would be needed.
Given this file:
abc: A B C D E
abc: 1 2 3 4 5
abc: 1 c9 A 7f
def D E F G H
def: 10 11 12 23 99
… this regex matches abc: 1 2 3 4 5 while excluding abc: 1 c9 A 7f — it also allows variable whitespace and trailing whitespace.
With any sed:
$ sed -n 's/^abc: \([0-9 ]*\)$/\1/p' file
1 2 3 4 5
I have a calculated value (in column H) which gives the number of trailing 0s I'd like to trim from the right of a cell (column E). But I only want to remove 0s; if there are other characters they should remain.
Examples:
E | H | Output
--+---------+--------
3 | 0110A00 | 0110A
3 | 0110A0B | 0110A0B
1 | 0110A00 | 0110A0
Any ideas? I'd like to avoid macros or masses of nested IFs if possible.
Use:
=LEFT(H1,MAX(AGGREGATE(14,6,ROW(INDEX(A:A,1):INDEX(A:A,LEN(H1)))/(MID(H1,ROW(INDEX(A:A,1):INDEX(A:A,LEN(H1))),1)<>"0"),1),LEN(H1)-E1))
I'm trying to calculate a sum numbers positioned on separate lines using C shell.
I must do it with specific commands using pipes.
There is a number of commands: comand.. | comand.. | (comands...)
printing lines in the following form:
1
2
8
4
7
The result should be 22, since 1 + 2 + 8 + 4 + 7 = 22.
I tried ... | bc | tr "\n" "+" | bc, but it didn't work.
I can't use AWK, or variables. That is why I am asking for help.
You actually can use the C shell variables, as they are part of the syntax. Without using variables, you need to pipe, and pipe again:
your-command | sed '2~1 s/^/+/' | xargs | bc
The sed command prepends plus character to all lines starting from the second; xargs joins the lines as a sequence of arguments.
The SED expression can be improved to filter out non-numeric lines:
'/^[^0-9]\+$/ d; 2~1 s/\([0-9]\+\)/+\1/'
I am finding slicing in Python a bit very difficult. Lets say if I want the first five and last five characters of a phrase to display how do i go about it. For example:
words = input("Enter a word ")
slice = words[:2]
print(slice)
You can use negative indexing for slice from end :
>>> s="teststring"
>>>
>>> s[-5:]
'tring'
>>> s[:5]
'tests'
Actually a slice notation observes the following law :
[start:end:step]
One way to remember how slices work is to think of the indices as pointing between characters, with the left edge of the first character numbered 0. Then the right edge of the last character of a string of n characters has index n, for example:
+---+---+---+---+---+---+
| P | y | t | h | o | n |
+---+---+---+---+---+---+
0 1 2 3 4 5 6
-6 -5 -4 -3 -2 -1
Read more about slicing https://docs.python.org/2/tutorial/introduction.html#strings
And https://docs.python.org/2.3/whatsnew/section-slices.html
How would I round the result from two divided numbers, e.g.
3/2
As when I do
testOne=$((3/2))
$testOne contains "1" when it should have rounded up to "2" as the answer from 3/2=1.5
To do rounding up in truncating arithmetic, simply add (denom-1) to the numerator.
Example, rounding down:
N/2
M/5
K/16
Example, rounding up:
(N+1)/2
(M+4)/5
(K+15)/16
To do round-to-nearest, add (denom/2) to the numerator (halves will round up):
(N+1)/2
(M+2)/5
(K+8)/16
Good Solution is to get Nearest Round Number is
var=2.5
echo $var | awk '{print int($1+0.5)}'
Logic is simple if the var decimal value is less then .5 then closest value taken is integer value. Well if decimal value is more than .5 then next integer value gets added and since awk then takes only integer part. Issue solved
bash will not give you correct result of 3/2 since it doesn't do floating pt maths. you can use tools like awk
$ awk 'BEGIN { rounded = sprintf("%.0f", 3/2); print rounded }'
2
or bc
$ printf "%.0f" $(echo "scale=2;3/2" | bc)
2
If you have integer division of positive numbers which rounds toward zero, then you can add one less than the divisor to the dividend to make it round up.
That is to say, replace X / Y with (X + Y - 1) / Y.
Proof:
Case 1: X = k * Y (X is integer multiple of Y): In this case, we have (k * Y + Y - 1) / Y, which splits into (k * Y) / Y + (Y - 1) / Y. The (Y - 1)/Y part rounds to zero, and we are left with a quotient of k. This is exactly what we want: when the inputs are divisible, we want the adjusted calculation to still produce the correct exact quotient.
Case 2: X = k * Y + m where 0 < m < Y (X is not a multiple of Y). In this case we have a numerator of k * Y + m + Y - 1, or k * Y + Y + m - 1, and we can write the division out as (k * Y)/Y + Y/Y + (m - 1)/Y. Since 0 < m < Y, 0 <= m - 1 < Y - 1, and so the last term (m - 1)/Y goes to zero. We are left with (k * Y)/Y + Y/Y which work out to k + 1. This shows that the behavior rounds up. If we have an X which is a k multiple of Y, if we add just 1 to it, the division rounds up to k + 1.
But this rounding is extremely opposite; all inexact divisions go away from zero. How about something in between?
That can be achieved by "priming" the numerator with Y/2. Instead of X/Y, calculate (X+Y/2)/Y. Instead of proof, let's go empirical on this one:
$ round()
> {
> echo $((($1 + $2/2) / $2))
> }
$ round 4 10
0
$ round 5 10
1
$ round 6 10
1
$ round 9 10
1
$ round 10 10
1
$ round 14 10
1
$ round 15 10
2
Whenever the divisor is an even, positive number, if the numerator is congruent to half that number, it rounds up, and rounds down if it is one less than that.
For instance, round 6 12 goes to 1, as do all values which are equal to 6, modulo 12, like 18 (which goes to 2) and so on. round 5 12 goes down to 0.
For odd numbers, the behavior is correct. None of the exact rational numbers are midway between two consecutive multiples. For instance, with a denominator of 11 we have 5/11 < 5.5/11 (exact middle) < 6/11; and round 5 11 rounds down, whereas round 6 11 rounds up.
Given a floating point value, we can round it trivially with printf:
# round $1 to $2 decimal places
round() {
printf "%.${2:-0}f" "$1"
}
Then,
# do some math, bc style
math() {
echo "$*" | bc -l
}
$ echo "Pi, to five decimal places, is $(round $(math "4*a(1)") 5)"
Pi, to five decimal places, is 3.14159
Or, to use the original request:
$ echo "3/2, rounded to the nearest integer, is $(round $(math "3/2") 0)"
3/2, rounded to the nearest integer, is 2
To round up you can use modulus.
The second part of the equation will add to True if there's a remainder. (True = 1; False = 0)
ex: 3/2
answer=$(((3 / 2) + (3 % 2 > 0)))
echo $answer
2
ex: 100 / 2
answer=$(((100 / 2) + (100 % 2 > 0)))
echo $answer
50
ex: 100 / 3
answer=$(((100 / 3) + (100 % 3 > 0)))
echo $answer
34
If the decimal separator is comma (eg : LC_NUMERIC=fr_FR.UTF-8, see here):
$ printf "%.0f" $(echo "scale=2;3/2" | bc)
bash: printf: 1.50: nombre non valable
0
Substitution is needed for ghostdog74 solution :
$ printf "%.0f" $(echo "scale=2;3/2" | bc | sed 's/[.]/,/')
2
or
$ printf "%.0f" $(echo "scale=2;3/2" | bc | tr '.' ',')
2
Another solution is to do the division within a python command. For example:
$ numerator=90
$ denominator=7
$ python -c "print (round(${numerator}.0 / ${denominator}.0))"
Seems less archaic to me than using awk.
I think this should be enough.
$ echo "3/2" | bc
Following worked for me.
#!/bin/bash
function float() {
bc << EOF
num = $1;
base = num / 1;
if (((num - base) * 10) > 1 )
base += 1;
print base;
EOF
echo ""
}
float 3.2