So as an input, i get echo [number]. For example: echo 5.
I need to get as output the sequence of numbers from 1 to [number].
So if I get 5 as input, I need: 1 2 3 4 5 (all on a separate line).
I know I can use seq 5 to get 1 2 3 4 5 but the issue is that I need to use pipes.
So the final command should be like this: echo 5 | seq [number] which should give 1 2 3 4 5 as output. My issue is that I don't know how to get the output from echo as my input for seq.
Assuming that echo 5 is an example replacement of an unknown program that will write a single number to stdout and that this output should be used as an argument for seq, you could use a script like this:
file seqstdin:
#!/bin/sh
read num
seq "$num"
You can use it like
echo 5 | ./seqstdin
to get the output
1
2
3
4
5
You can also write everything in a single line, e.g.
echo '5'| { read num; seq "$num"; }
Notes:
This code does not contain any error handling. It uses the first line of input as an argument for seq. If seq does not accept this value it will print an error message.
I did not use read -r or IFS= because I expect the input to be a number suitable for seq. With other input you might get unexpected results.
You can use the output of the echo command as follows:
seq $(echo 5)
In case you're dealing with a variable, you might do:
var=5
echo $var
seq $var
Related
I would like to split the following file based on the pattern ABC:
ABC
4
5
6
ABC
1
2
3
ABC
1
2
3
4
ABC
8
2
3
to get file1:
ABC
4
5
6
file2:
ABC
1
2
3
etc.
Looking at the docs of man csplit: csplit my_file /regex/ {num}.
I can split this file using: csplit my_file '/^ABC$/' {2} but this requires me to put in a number for {num}. When I try to match with {*} which suppose to repeat the pattern as much as possible, i get the error:
csplit: *}: bad repetition count
I am using a zshell.
To split a file on a pattern like this, I would turn to awk:
awk 'BEGIN { i=0; }
/^ABC/ { ++i; }
{ print >> "file" i }' < input
This reads lines from the file named input; before reading any lines, the BEGIN section explicitly initializes an "i" variable to zero; variables in awk default to zero, but it never hurts to be explicit. The "i" variable is our index to the serial filenames.
Subsequently, each line that starts with "ABC" will increment this "i" variable.
Any and every line in the file will then be printed (in append mode) to the file name that's generated from the text "file" and the current value of the "i" variable.
I have got a big file ( arounf 80K lines )
my main goal is to find the patterns and pring for example 10 lines before and 10 lines after the pattern .
the pattern accures multiple times across the file .
using the grep command :
grep -i <my_pattern>* -B 10 -A 10 <my_file>
i get only some of the data , i think it must be something related to the buffer size ....
i need a command ( grep , sed , awk ) that will handle all the matching
and will print 10 line before and after the pattern ...
Example :
my patterns hides here :
a
b
c
pattern_234
c
b
a
a
b
c
pattern_567
c
b
a
this happens multiple times across the file .
running this command :
grep -i pattern_* -B 3 -A 3 <my_file>
will get he right output :
a
b
c
c
b
a
a
b
c
c
b
it works but not full time
if i have 80 patterns not all the 80 will be shown
awk to the rescue
awk -vn=4 # pass the argument of context line count
'{
for(i=1;i<=n;i++) # store the past n lines in an indexed array
p[i]=p[i+1];
p[n+1]=$0
}
/pattern/ # if pattern matched
{
c=n+1; # set the counter to after match line count
for(i=1;i<=n;i++) # print previously saved entries
print p[i]
}
c-->0' # print the lines after match until counter runs out
will print 4 lines before and 4 lines after the match of pattern, change the value of n as per your need.
if non-symmetric before/after you need two variables
awk -vb=2 -va=3 '{for(i=1;i<=b;i++) p[i]=p[i+1];p[b+1]=$0} /pattern/{c=a+1;for(i=1;i<=b;i++) print p[i]} c-->0'
lets say I have a script like this:
num1 = 3
for i in $num1
do
echo "test $num1"
echo "abcd"
echo "foo"
done
and I want to ouput the echo to a log file for each value in num1, how would one do that? So when this runs, it should create log1.log, log2.log, and log3.log.
Add a redirection of echo's output to a file:
num1 = 3
for i in $num1
do
echo "test $num1" > log$i.log
done
This will produce a single file called log3 with the content test 3.
Maybe you want to use curly braces (ksh) to get the sequence 1 2 3 and each file to have a different content based on i:
num1=3
for i in {1..$num1}
do
echo "$i" > log$i.log
done
This will produce 3 files names log1.log, log2.log and log3.log with the content 1 2 and 3 respectively.
I have a script where the sql output of the function is multiple rows (one column) and I'm trying to loop through those for loop function but can't get to seem to get it to work...
rslt=sqlquery {}
echo $rslt
1
2
3
4
for i in $rslt
do
echo "lvl$i"
done
but for the loop...I keep getting this back four times
lvl1
2
3
4
where as I want to get this back...
lvl1
lvl2
lvl3
lvl4
how do I get that?
In order to get the needed result in your script you need to take $rslt under double quotes ". This will ensure that you are not loosing the new lines \n from you result which you are expecting to have in the loop.
for i in "$rslt"
do
echo "lvl$i"
done
To loop over the values in a ksh array, you need to use the ${array[#]} syntax:
$ set -A rslt 1 2 3 4
$ for i in ${rslt[#]}
> do
> echo "lvl$i"
> done
lvl1
lvl2
lvl3
lvl4
If I have an array:
x=( a:1 b:2 c:3 )
How can I split each element of the array on the colon? I'm trying to do this in order to form an associative array.
I've tried several variations on this, but none seem to work:
print -l ${(s,:,)x}
Is this possible? If so, what am I missing?
Ok - further thinking got me to this solution, that might probably be applicable to the problem behind the question asked:
Loop through the array x!
> x=(a:1 b:2 c:3)
> typeset -A z
> for i in $x; do z+=(${(s,:,)i}); done
> echo $z
1 2 3
> echo ${z[a]}
1
I hope that's more helpful than the first answer(s) :-)
Since x is an array, you shouldn't forget the [#], i.e. print ${(s,:,)x[#]}; thus your code becomes print -l ${(s,:,)x[#]}; but the solution is still another step:
> typeset -A z
> x="a:1 b:2 c:3"
> z=($(echo ${(s,:,)x}))
> echo $z[a]
1
The assignement to the associative array is done with the output of the echo statement.
To clarify further and include your original example x:
> typeset -A z
> x=(a:1 b:2 c:3)
> z=($(echo ${(s,:,)x[#]}))
> echo ${z[a]}
1
> echo ${z[b]}
2
(edit: switched thoughts midwriting :-D, should make more sense now)
(edit 2: striked brainf*rt - similarities between zsh and bash aren't as broad as I assumed)
typeset -A x will make x an associative array
$ typeset -A x
$ x=( a 1 b 2 c 3 )
$ echo $x[a]
1
$ echo $x[c]
3
$ x[d]=5
$ echo $x[d]
5
But i don't know how to split on the colon if you need to start from the string "a:1 b:2 c:3".