bash 如何将awk结果输出到文件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2126456/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to output awk result to file
提问by Erik Sapir
I am trying to output 'awk' result to file in my script, with no success. Using '>' does not work, why?
我正在尝试将“awk”结果输出到我的脚本中的文件中,但没有成功。使用“>”不起作用,为什么?
for a in $(find $OUPUT_DIR/ -maxdepth 1 -mindepth 1 -type d -printf "%P\n")
do
echo $a is a directory
awk -F, '{ if ( == '"$a"') print echo 'hello' | awk '{print}' >qq.tmp
}' $OUPUT_DIR/CDRNOutput_${CDR_DATE}.csv > $OUPUT_DIR/$a/CDR-${CDR_DATE}.csv
done
回答by paxdiablo
Output redirection is generally a feature of the shell you're working with and, given how much use it gets, I'd be pretty amazed if you'd found a bug in it :-)
输出重定向通常是您正在使用的 shell 的一个功能,考虑到它的使用量,如果您发现其中的错误,我会非常惊讶:-)
Are you sure you're not trying to do redirection with awk
itself rather than the shell?
您确定您不是在尝试使用awk
自身而不是外壳进行重定向吗?
What happens when you do:
当你这样做时会发生什么:
for a in $(find $OUPUT_DIR/ -maxdepth 1 -mindepth 1 -type d -printf "%P\n")
do
echo $a is a directory
awk -F, '{ if ( == '"$a"') print awk -F, -v a=$a '{ if (==a) print 1,2,3,4,5,6,7,8,9,XpVm,11
}' ...
}' $OUPUT_DIR/CDRNOutput_${CDR_DATE}.csv > $OUPUT_DIR/$a/CDR-${CDR_DATE}.csv
done
Update:
更新:
If this is your code as stated, it's because the $a
is not being expanded by your shell script since the awk
command is within single quotes.
如果这是您所说的代码,那是因为$a
您的 shell 脚本没有扩展该awk
命令,因为该命令位于单引号内。
for a in $(find . -maxdepth 1 -mindepth 1 -type d -printf "%P\n" | grep -v '^\.')
do
echo $a is a directory
awk -F, '{
if ( == '"$a"') {
print workspace is a directory
NO
Documents is a directory
NO
XpVm is a directory
NO
Downloads is a directory
NO
} else {
print "NO";
}
}' ./CDRNOutput_X.csv
done
What I tend to do is pass in specific values to awk
using the -v
option, something like (in your case):
我倾向于做的是将特定值传递给awk
使用该-v
选项,例如(在您的情况下):
for a in $(find . -maxdepth 1 -mindepth 1 -type d -printf "%P\n" | grep -v '^\.')
do
echo $a is a directory
awk -F, -v a=$a '{
if ( == a) {
print workspace is a directory
NO
Documents is a directory
NO
XpVm is a directory
1,2,3,4,5,6,7,8,9,XpVm,11
Downloads is a directory
NO
} else {
print "NO"
}
}' ./CDRNOutput_X.csv
done
Then the variables become first-class awk
citizens without having to worry about who's doing the expansion.
然后变量成为一等awk
公民,而不必担心谁在进行扩展。
Further update:
进一步更新:
I'm standing behind my original advice. There's something definitely screwy with the method chosen.
我支持我最初的建议。选择的方法肯定有问题。
I have a directory in my home directory called XpVm (among others) and I've created the file CDRNOutput_X.csv
containing the single line:
我的主目录中有一个名为 XpVm(以及其他)的目录,我创建了CDRNOutput_X.csv
包含单行的文件:
for a in $(find . -maxdepth 1 -mindepth 1 -type d -printf "%P\n" | grep -v '^\.')
do
echo $a is a directory
awk -F, '{
if ( == '"$a"') {
print tmp is a directory
NO
tmp2 is a directory
NO
} else {
print "NO";
}
}' ./CDRNOutput_X.csv
done
When I execute:
当我执行:
if ( == tmp) {
(I've stripped out directories starting with .
since they were causing another problem), I get this output:
(我已经删除了目录,.
因为它们引起了另一个问题),我得到了这个输出:
if ( == "tmp") {
which is clearly not what is expected. However, when I use the -v
option to awk
as I originally suggested, the command:
这显然不是预期的。但是,当我按照最初的建议使用该-v
选项时awk
,命令:
#!/bin/bash
for a in $(find . -maxdepth 1 -mindepth 1 -type d -printf "%P\n" | grep -v '^\.')
do
echo $a is a directory
awk -F, '{
if ( == "'"$a"'") {
print tmp is a directory
1,2,3,4,5,6,7,8,9,tmp,11
tmp2 is a directory
NO
} else {
print "NO";
}
}' ./CDRNOutput_X.csv
done
(the only difference being the changes to a
), I get:
(唯一的区别是对 的更改a
),我得到:
'{ if ( == '"$a"') print '{ if ( == "'"$a"'") print #!/bin/bash
CDR_DATE="somedate"
infile=CDRNOutput_${CDR_DATE}.csv
outfile=CDR-${CDR_DATE}.csv
OUPUT_DIR="/some/dir"
cd $OUPUT_DIR
for dir in */
do
echo "${dir%/*} is a directory"
dir=${dir%/*}
while read -r a b c d e f g h i j k
do
case "$j" in
$dir) echo $a $b $c $d $e $f $g $h $i $j $k >> $dir/$outfile;;
esac
done < $infile
done
}'
}'
which is correct.
哪个是正确的。
Final update (hopefully):
最终更新(希望如此):
I think I have the problem solved. I'm on a different machine now (so the directory names are simply tmp
and tmp2
) and, when I run the original script:
我想我已经解决了问题。我现在在另一台机器上(所以目录名称只是tmp
和tmp2
),并且当我运行原始脚本时:
with a modified CDRNOutput_X.csv
containing tmp
instead of XpVm
, I get:
使用修改后的CDRNOutput_X.csv
包含tmp
而不是XpVm
,我得到:
That's because the if
statement is being seen by awk
as:
那是因为该if
声明被视为awk
:
(without quotes, since the quotes are actually outsidethe awk
string being used to surround the directory name). This will test $10
for equality against the awk
variable called tmp
rather than the actual string "tmp"
. What you need is to make sure that the quotes are insidethe awk
script, like:
(没有引号,因为引号实际上在awk
用于包围目录名称的字符串之外)。这将$10
针对被awk
调用的变量tmp
而不是实际的 string测试是否相等"tmp"
。你需要的是确保引号是里面的awk
脚本,如:
and you can do this with the following script (only the if
line has changed):
您可以使用以下脚本执行此操作(仅if
更改了该行):
Note that the double quotes are duplicated. I've still kept the double quotes immediately around $a
in case someone's committed the heinous crime of creating a file with a space in it :-)
请注意,双引号是重复的。我仍然立即保留双引号$a
,以防有人犯下了创建带有空格的文件的滔天罪行:-)
Running that script produces:
运行该脚本会产生:
##代码##which is what I think you were aiming for.
这就是我认为你的目标。
So, the upshot is, if you don't want to use awk
variables, you can just change your awk string from:
所以,结果是,如果你不想使用awk
变量,你可以改变你的 awk 字符串:
to:
到:
##代码##and it should function okay.
它应该可以正常运行。
回答by ghostdog74
since you have find command with -mindepth and maxdepth set to 1, you can just do it with the shell
由于您已将 -mindepth 和 maxdepth 设置为 1 的 find 命令,您可以使用 shell 执行此操作
##代码##