I am using ksh. On this link http://www.shelldorado.com/shelltips/advanced.html#redir , there is an example for saving stdout, stderr and both into 3 separate files.
((./program 2>&1 1>&3 | tee ~/err.txt) 3>&1 1>&2 | tee ~/out.txt) > ~/mix.txt 2>&1
I tried that but I am getting below error:
ksh: syntax error: `(' unexpected
Please advice.
Pretty much works for me:
$ ksh
$ ps | grep "$$"
6987 pts/6 00:00:00 ksh
$ cat program.sh
#!/bin/sh
echo "err" 1>&2
echo "out"
$ ((./program.sh 2>&1 1>&3 | tee err.txt) 3>&1 1>&2 | tee out.txt) > mix.txt 2>&1
$ cat out.txt
out
$ cat err.txt
err
$ cat mix.txt
err
out
Related
I have a file with below contents
cat file1.dat
anuÇ89Çhyd
binduÇ45Çchennai
I would like to print the second column with Ç as delimiter.
output should be
89
45
The manpage of awk mentions the following:
-F fs
--field-separator fs
Use fs for the input field separator (the value of the FS predefined variable).
So, this command does what you want:
cat file1.dat | awk -F'Ç' '{print $2}'
Given:
$ cat file
anuÇ89Çhyd
binduÇ45Çchennai
You can use cut:
$ cut -f 2 -d 'Ç' file
awk:
$ awk -F'Ç' '{print $2}' file
sed:
$ sed -E 's/^[^Ç]*Ç([^Ç]*).*/\1/' file
GNU grep:
$ grep -oP '^[^Ç]*Ç\K[^Ç]+(?=Ç)' file
Perl:
$ perl -lnE 'print $1 if /^[^Ç]*Ç([^Ç]+)Ç/' file
All those print:
89
45
I want the variable to be passed as below.
a=110600002019
b=120700002019
sed "$(sed -n '/$a/ =' tmuser.cf | tail -n 1)" 's/$a /$b/' tmuser.cf
sed "$(sed -n "/$a/ =" tmuser.cf | tail -n 1) s/$a /$b/" tmuser.cf
Worked for me. I made a small test file
cat tmuser.cf
a
110600002019
b
c
120700002019
Wasn't sure about the 120700002019 so I put it in the file.
The output from the script above is
a
120700002019
b
c
120700002019
Note that you can learn a lot for debugging a problem like this by wrapping your command with
set -vx ; ... your cmnds .... ; set +vx
Doing so yielded the first clue
sed "$(sed -n '/$a/ =' tmuser.cf | tail -n 1)" 's/$a /$b/' tmuser.cf
1 >sed -n '/$a/ =' tmuser.cf
1 >tail -n 1
1 >sed '' 's/$a /$b/' tmuser.cf
sed: s/$a /$b/: cannot open [No such file or directory]
a
110600002019
b
c
120700002019
None of the variables are being replaced with their values. You need to use dbl-quotes so variables can be substituted.
And the error message
sed: s/$a /$b/: cannot open [No such file or directory]
tells us that sed thinks that s/$a /$b/ is a filename, not a command. All commands have to appear as one unbroken string to the shell that is passing them to sed, so notice how I've changed
...| tail -n 1)" 's/$a /$b/'...
to
...| tail -n 1) s/$a /$b/"....
IHTH
Is there a way to evaluate a string as a math expression in awk?
balter#spectre3:~$ echo "sin(0.3) 0.3" | awk '{print $1,sin($2)}'
sin(0.3) 0.29552
I would like to know a way to also have the first input evaluated to 0.29552.
You can just create your own eval function which calls awk again to execute whatever command you want it to:
$ cat tst.awk
{ print eval($1), sin($2) }
function eval(str, cmd,line,ret) {
cmd = "awk \047BEGIN{print " str "; exit}\047"
if ( (cmd | getline line) > 0 ) {
ret = line
}
close(cmd)
return ret
}
$ echo 'sin(0.3) 0.3' | awk -f tst.awk
0.29552 0.29552
$ echo '4*7 0.3' | awk -f tst.awk
28 0.29552
$ echo 'tolower("FOO") 0.3' | awk -f tst.awk
foo 0.29552
awk lacks an eval(...) function. This means that you cannot do string to code translation based on input after the awk program initializes. Ok, perhaps it could be done, but not without writing your own parsing and evaluation engine in awk.
I would recommend using bc for this effort, like
[edwbuck#phoenix ~]$ echo "s(0.3)" | bc -l
.29552020666133957510
Note that this would require sin to be shortened to s as that's the bc sine operation.
Here's a simple one liner!
math(){ awk "BEGIN{printf $1}"; }
Examples of use:
math 1+1
Yields "2"
math 'sqrt(25)'
Yeilds "5"
x=100; y=5; math "sqrt($x) + $y"
Yeilds "15"
With gawk version 4.1.2 :
echo "sin(0.3) 0.3" | awk '{split($1,a,/[()]/);f=a[1];print #f(a[2]),sin($2)}'
It's ok with tolower(FOO) too.
You can try Perl as it has eval() function.
$ echo "sin(0.3)" | perl -ne ' print eval '
0.29552020666134
$
For the given input,
$ echo "sin(0.3) 0.3" | perl -ne ' /(\S+)\s+(\S+)/ and print eval($1), " ", $2 '
0.29552020666134 0.3
$
file.txt is as below :
gui : 789
gui : 789
gui : 789
gui : 789
abc : 120
The followibng gives o/p as
$ grep -n "gui : 789" file.txt | cut -f1 -d:
1
2
3
4
If there are N number of such gui : 789 , how to store the line numbers of the same ?
You can use this awk 1 liner:
awk '/gui : 789/{print NR}' file
To process this inside a loop:
while read l
do
echo $l
done < <(awk '/gui : 789/{print NR}' file)
EDIT: These command will work for any number of matches in the file. To store output of above line numbers in an array:
arr=( $(awk '/gui : 789/{print NR}' x) )
later on process these array elements as:
echo ${arr[0]}
echo ${arr[1]}
...
echo ${arr[5]}
Like this:
LINES=$(grep -n "gui : 789" file.txt | cut -f1 -d:)
The "LINES" variable will have: "1 2 3 4".
Note: your question was very generic. This answer will work for Bash or Korn Shell.
If you want to do processing with each line, you can do something like:
grep -n "gui : 789" file.txt | cut -f1 -d: | while read lineno; do
: # process using $lineno
done
The Unix cut command takes a list of fields, but not the order that I need it in.
$ echo 1,2,3,4,5,6 | cut -d, -f 1,2,3,5
1,2,3,5
$ echo 1,2,3,4,5,6 | cut -d, -f 1,3,2,5
1,2,3,5
However, I would like a Unix shell command that will give me the fields in the order that I specify.
Use:
pax> echo 1,2,3,4,5,6 | awk -F, 'BEGIN {OFS=","}{print $1,$3,$2,$5}'
1,3,2,5
or:
pax> echo 1,2,3,4,5,6 | awk -F, -vOFS=, '{print $1,$3,$2,$5}'
1,3,2,5
Or just use the shell
$ set -f
$ string="1,2,3,4,5"
$ IFS=","
$ set -- $string
$ echo $1 $3 $2 $5
1 3 2 5
Awk based solution is elegant. Here is a perl based solution:
echo 1,2,3,4,5,6 | perl -e '#order=(1,3,2,5);#a=split/,/,<>;for(#order){print $a[$_-1];}'