【问题标题】:Use awk to replace start and end of each line in a large file使用 awk 替换大文件中每一行的开头和结尾
【发布时间】:2018-08-01 02:08:53
【问题描述】:

我有一系列大型 (25-250MB) 制表符分隔的文本文件,我需要将其转换为 SQL 格式的批量插入。我对 awk 非常陌生,所以我不知道自己在做什么。我所知道的是,我需要解决方案以尽可能短的时间处理数据。结果,我的尝试是微弱的。我试图通过 sed(总集群)和 awk 在每个文件中分别进行三个单独的传递来实现以下目标;就这样……

通过 1:awk '{gsub(/%J\t/,"\(\'")}1' file.txt

通过 2:awk '{gsub(/\n,"\'\)\n")}1' file.txt

通过 3:awk '{gsub(/\t/,"\',\'")}1' file.txt

由于我严重缺乏 awk 经验,当我尝试上述操作时,终端会切换到新提示符,就像它在等待更多信息而不是执行命令一样。

以下是整个文件中数据格式的示例。

每一行的结构如下:

%J\t数据\t数据\t数据\t数据\t数据\n

我想使用 awk 或其他东西将每一行重组为以下格式:

('DATA','DATA','DATA','DATA','DATA',@id)\n

注意:如果我的格式不正确,我深表歉意。这是我在 Stack 上的第一篇文章。

提前感谢大家的宝贵时间和帮助!

【问题讨论】:

  • 展示你的尝试
  • 请发布 3 个简单的内容,1- 代码标签中的示例输入,2- 代码标签中的示例输出,3- 您的条件和您在帖子中的尝试。
  • 什么是@id?如果您打算对术语进行定义,那将是受欢迎的。您的尝试失败了,因为单引号内有单引号。
  • 嗨 JNevill,@id 是乱码。我正在尝试构建的是一组 MySQL BULK INSERT。我已经转义了单引号。这对 awk 不起作用吗?
  • shell 在 Awk 运行之前解释引号。您不能在 Bourne shell 中的单引号内转义单引号(尽管可以使用其他一些变通方法)。

标签: regex linux awk gawk


【解决方案1】:

这样的事情应该可以解决问题:

awk -F"\t" -v q="'" '{printf "("}{for (i=2;i<=NF;i++){printf "%s\t", q $i q}}{print "@id)"}'

这说:

  1. 用制表符分割每条记录-F"\t"
  2. 将变量q 设置为单引号:-v q="'"
  3. 打印出一个开始的括号'{printf "("}
  4. 从第 2 列 for (i=2;i&lt;=NF;i++) 开始循环遍历记录中的每一列
  5. 打印列,后跟用单引号括住列的制表符(使用变量):printf "%s\t", q $i q
  6. 最后使用print 命令打印出文字@id,后跟右括号,以便在打印结束时弹出回车符:print NR")"


:~> cat testfile
%J      D1      D2      D3
%J      D2      D3      D4
:~> awk -F"\t" -v q="'" '{printf "("}{for (i=2;i<=NF;i++){printf "%s\t", q $i q}}{print "@id)"}' testfile
('D1'   'D2'    'D3'    @id)
('D2'   'D3'    'D4'    @id)

【讨论】:

  • 谢谢你,JNevill!感谢您的回答和慷慨的解释。我会告诉你进展如何。
  • 很高兴我能帮上忙。我认为这个答案可以通过使用 ORS 和 OFS 变量更简洁一些,但这将完成工作。
【解决方案2】:

使用(g)awk 选项并使用@JNevill 的输入文件

$ awk -F'\t' -v RS='%J' -v ORS="',@id)\n" -v OFS="','" -v q="('" 'NF{$1=q $1; print}' file

('D1','D2','D3',@id)
('D2','D3','D4',@id)

【讨论】:

  • 您的数据文件中可能有一个\r,如果来自Windows,也许运行dos2unix
  • 嗨,karakfa,这让我更接近了。我有两个问题:在我的测试中,'@id) 之前出现了一个 \n,它正在替换空格和制表符。输入:%J 1381 443 3 201-GE General 7850410 Control Systems 443 My your code: awk -v RS='%J' -v ORS="',@id)\n" -v OFS="','" -vq="'" 'NF{$1="(" q $1; print}' origin.txt > test.txt` OUTPUT: ('1381','443','3','201-GE','General','7850410','Control','Systems' ,'Engineering','443',@id) 有什么想法吗?我还在努力。
  • 添加 -F"\t" 修复了被替换的空格。
【解决方案3】:

这是有效的。首先,感谢 JNevill 和 karakfa!你们都让这成为可能,我学到了很多!!

INPUT
%J  1381    443 3   201-GE  General 7850410 Control Systems 443
%J  1382    443 3   201-GE  General 7850250 Mechanical  443
%J  1383    443 3   201-GE  General 7850400 Electrical  443

CODE
dos2unix test.txt // Ran this first to clean up the '\r's in the file.
awk -F"\t" -v RS='%J\t' -v ORS="',@id)\n" -v OFS="','" -v q="'" 'NF{$1="("q $1; print}' test.txt > test_.txt // Then ran this to finish the job

OUTPUT
('1381','443','3','201-GE','General','7850410','Control Systems','443',@id)
('1382','443','3','201-GE','General','7850250','Mechanical','443',@id)
('1383','443','3','201-GE','General','7850400','Electrical','443',@id)

多田!再次感谢。现在我只需要做一些 GC 就可以了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-12-17
    • 1970-01-01
    • 2020-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-14
    • 1970-01-01
    相关资源
    最近更新 更多