使用awk时显示致命错误:无法打开管道(打开的文件太多)错误

使用awk时显示致命错误:无法打开管道(打开的文件太多)错误,awk,Awk,我试图用命令“tr”和“awk”屏蔽文件,但失败了,错误是致命的:无法打开管道(打开的管道太多)错误。该文件有大约1000000条记录,数量相当大。 下面是我正在尝试的代码:- awk - F "|" - v OFS="|" '{ "echo \""$1"\" | tr \" 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\" \" QWERTYUIOPASDFGHJKLZXCVBNM9876543210mnbvcxz

我试图用命令“tr”和“awk”屏蔽文件,但失败了,错误是致命的:无法打开管道(打开的管道太多)错误。该文件有大约1000000条记录,数量相当大。 下面是我正在尝试的代码:-

awk - F "|" - v OFS="|" '{ "echo \""$1"\" | tr \" 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\" \" QWERTYUIOPASDFGHJKLZXCVBNM9876543210mnbvcxzlkjhgfdsapoiuytrewq\"" | get line $1}1' FILE.CSV > test.CSV
它显示错误:-

awk: (FILENAME=- FNR=1019) fatal: cannot open pipe `echo ""TTP_123"" | tr "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" "QWERTYUIOPASDFGHJKLZXCVBNM9876543210mnbvcxzlkjhgfdsapoiuytrewq"' (Too many open pipes)
请让我知道我做错了什么 还有一个注释:任何数量的列都可以用于掩蔽,并且可以位于任何位置。在本例中,我选择了1列和2列位置,但可以是3列和10列,也可以是5列、7列和25列 谢谢
AJ

您可以在
awk
中进行映射,而无需对每一行进行系统调用,或者简单地进行映射

paste -d'|' <(cut -d'|' -f1 file | tr '0-9' 'a-z') <(cut -d'|' -f2- file)

paste-d'|'这并不能回答您的问题,但您可以将
tr
实现为一个awk函数,这样就不必产生大量的外部进程

$ cat tr.awk

function tr(str, from, to,       s,i,c,idx) {
    s = ""
    for (i=1; i<=length($str); i++) {
        c = substr(str, i, 1)
        idx = index(from, c)
        s = s (idx == 0 ? c : substr(to, idx, 1))
    }
    return s
}
{
    print $1, tr($1,
        " 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
        " QWERTYUIOPASDFGHJKLZXCVBNM9876543210mnbvcxzlkjhgfdsapoiuytrewq")
}

首先,在
-
F
v
之间不能有空格

我本来打算建议您使用sed
sed
,但由于您只想翻译第一列,所以这并不容易

不幸的是,
awk
没有内置的
tr
功能,因此您必须像现在这样使用shell,只需关闭管道即可:

awk -F "|" -v OFS="|" '{ 
    command="echo \"\\"$1"\\\" | tr \" 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\" \" QWERTYUIOPASDFGHJKLZXCVBNM9876543210mnbvcxzlkjhgfdsapoiuytrewq\""
    command | getline $1
    close(command)
}1' FILE.CSV > test.CSV
但是,我建议使用
perl
,它可以进行字段拆分和字符转换:

perl -F'\|' -lane '$F[0] =~ tr/0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/QWERTYUIOPASDFGHJKLZXCVBNM9876543210mnbvcxzlkjhgfdsapoiuytrewq/; print join("|", @F)' FILE.CSV > test.CSV

或者,对于较短的命令行,只需将程序放入一个文件中,将
e
放在
-lane
中,并使用文件名而不是
“…”
命令。

不清楚,请在代码标记中向我们显示带有预期输出文件的示例输入文件,以便我们可以尝试帮助您。您每次都需要关闭管道。但这就是你要做的吗?为什么不使用
sed
?@RavinderSingh13抱歉,无法向您显示1000000条数据记录,因为这适用于1000条记录。请注意,我应该如何使用sed实现这一点,或者我应该如何使用Close处理我的代码?请告诉我,这就是为什么我提到了示例(当然只有几行),这意味着数据看起来是什么样的(即使它可能没有实际数据,也可能有伪值)我尝试了你的close命令解决方案,但它只对rest的1条起始记录有效。所有数据都没有转换,或者我们可以说被屏蔽了,但至少我没有面对错误,但我仍然想用你的解决方案屏蔽第1列的数据请让我知道,如果此解决方案适用于1条记录而不适用于其他记录,请让我知道我可以为多条记录执行哪些解决方案此解决方案适用于我,只更改每行的第一个字段(“201403310000”|“America”->“eqwtqrrwqqq”|“America”)。你想让它改变整行吗?不,凯文,只有第一列,至少我会再试一次,但在第一次,它只改变了第一条记录,其余的都和以前一样凯文,它仍然是一样的,只是第一行,它正在改变Unix脚本,不是rest。好吧,它对我有效,所以很难说你的问题是什么e可能是。你试过perl版本吗?嗨,Karakfa,当我用我的文件运行命令时,它挂起在一个地方,正在等待一些输入,我不知道为什么,你提供的输入对我有效。只需用一个示例文件进行测试。如果示例测试有效,那么验证你的数据文件。谢谢Glenn,这是一段有用的代码把它当作一门学问:)
perl -F'\|' -lane '$F[0] =~ tr/0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/QWERTYUIOPASDFGHJKLZXCVBNM9876543210mnbvcxzlkjhgfdsapoiuytrewq/; print join("|", @F)' FILE.CSV > test.CSV