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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 18:52:48  来源:igfitidea点击:

How to output awk result to file

linuxbashscriptingawk

提问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 awkitself 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 $ais not being expanded by your shell script since the awkcommand 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 awkusing the -voption, 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 awkcitizens 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.csvcontaining 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 -voption to awkas 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 tmpand tmp2) and, when I run the original script:

我想我已经解决了问题。我现在在另一台机器上(所以目录名称只是tmptmp2),并且当我运行原始脚本时:

##代码##

with a modified CDRNOutput_X.csvcontaining tmpinstead of XpVm, I get:

使用修改后的CDRNOutput_X.csv包含tmp而不是XpVm,我得到:

##代码##

That's because the ifstatement is being seen by awkas:

那是因为该if声明被视为awk

##代码##

(without quotes, since the quotes are actually outsidethe awkstring being used to surround the directory name). This will test $10for equality against the awkvariable called tmprather than the actual string "tmp". What you need is to make sure that the quotes are insidethe awkscript, like:

(没有引号,因为引号实际上awk用于包围目录名称的字符串之外)。这将$10针对被awk调用的变量tmp而不是实际的 string测试是否相等"tmp"。你需要的是确保引号是里面awk脚本,如:

##代码##

and you can do this with the following script (only the ifline has changed):

您可以使用以下脚本执行此操作(仅if更改了该行):

##代码##

Note that the double quotes are duplicated. I've still kept the double quotes immediately around $ain 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 awkvariables, 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 执行此操作

##代码##