【问题标题】:While using awk showing fatal : cannot open pipe ( Too many open files) error使用 awk 时显示致命:无法打开管道(打开的文件过多)错误
【发布时间】:2017-09-14 17:29:15
【问题描述】:

我试图使用命令“tr”和“awk”对文件进行屏蔽,但失败并出现致命错误:无法打开管道(打开的管道太多)错误。 FILE 有大约 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 列 谢谢 阿杰

【问题讨论】:

  • 不清楚,请在代码标签中向我们展示带有预期 output_file 的示例 Input_file,以便我们尝试帮助您。
  • 每次都需要关闭管道。但这就是你所做的一切吗?为什么不使用sed
  • @RavinderSingh13 抱歉无法显示 1000000 条数据记录,因为这适用于 1000 条记录
  • Kevin 我应该如何使用 SED 来实现这个,或者我应该如何在我的代码中使用 Close,你能告诉我吗
  • 这就是为什么我提到样本(当然只有几行),这意味着数据的样子(即使它可能没有实际数据,可能有虚拟值)但接近它以便我们可以知道你想要达到的目标。

标签: awk


【解决方案1】:

首先,-Fv 之间不能有空格。

我本来打算建议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 并使用文件名而不是'...' 命令。

【讨论】:

  • 嗨凯文,我尝试了你的关闭命令解决方案,但它只适用于 1 个起始记录,其余所有数据都没有被翻译,或者我们可以说被屏蔽,但至少我没有遇到错误,但是我仍然想至少用您的解决方案掩盖第一列的数据,请您告诉我,如果此解决方案适用于 1 条记录而不适用于其他记录,请告诉我我可以做的解决方案超过1 条记录
  • 这对我有用,只更改每行中的第一个字段(“201403310000”|“America”->“EQWTQRRWQQQQ”|“America”)。你想让它改变整条线吗?
  • 不,凯文只有第一列,至少我会再试一次,但第一次它只改变了第一条记录,其余的都和以前一样
  • 凯文它仍然是相同的只是第一行它正在改变 Unix 脚本而不是其余的
  • 嗯,它对我有用,所以很难说你的问题可能是什么。你试过 perl 版本吗?
【解决方案2】:

您可以在awk 中进行映射,而不是对每一行进行系统调用,或者干脆

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

用您的参数替换 tr 参数。

【讨论】:

  • 嗨 Karakfa,当我用我的文件运行命令时,它挂在了一个地方,正在等待一些输入,我不知道为什么
  • 不确定,您提供的输入对我有用。只需使用示例文件进行测试即可。如果示例测试有效,则验证您的数据文件。
【解决方案3】:

这不能回答您的问题,但您可以将 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")
}

例子:

$ printf "%s\n" hello wor-ld | awk -f tr.awk
hello KGCCN
wor-ld 3N8-CF

【讨论】:

  • 感谢 Glenn,这是一段有用的代码,可以把它当作学习:)
猜你喜欢
  • 2021-01-15
  • 1970-01-01
  • 2015-12-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-21
  • 2011-04-02
  • 2013-09-08
相关资源
最近更新 更多