使用 awk 命令从 csv 读取和打印第一 1000 行,然后再打印 1000 行,依此类推

Posted

技术标签:

【中文标题】使用 awk 命令从 csv 读取和打印第一 1000 行,然后再打印 1000 行,依此类推【英文标题】:To read and print 1st 1000 rows from a csv using awk command and then next 1000 and so on 【发布时间】:2022-01-18 15:49:36 【问题描述】:

我有一个大约 25k 行的 csv。我必须一次从第 1 列和第 2 列中选择 1000 行,然后再选择下 1000 行,依此类推。

我正在使用下面的命令,它可以很好地从列#1 和列#2 中提取所有值,即从两列中提取 25K 字段,我想选择 1-1000 之类的值,将它们放入我的 sql导出查询然后 1001-2000,2001-3000 等等,然后将值放在我的导出查询中的 WHERE IN 中,并将结果附加到 dbData.csv 文件中。

我的代码如下:

awk -F ',' 'NR > 2 print $1'  $INPUT > column1.txt
i=$(cat column1.txt | sed -n -e 'H;$x;s/\n/,/g;s/^,//;p;')

awk -F ',' 'NR > 2 print $2'  $INPUT > column2.txt
j=$(cat column2.txt | sed -n -e 'H;$x;s/\n/,/g;s/^,//;p;')

echo "Please wait - connecting to database..."
db2 connect to  $sourceDBStr user  user123 using pas123

db2 "export to dbData.csv of del select partnumber,language_id as LanguageId from  CATENTRY c , CATENTDESC cd where c.CATENTRY_ID=cd.CATENTRY_ID and c.PARTNUMBER in  ($i) and cd.language_id in ($j)"

【问题讨论】:

欢迎来到 SO,感谢您分享您的努力。请务必提及当您获取前 1000 行等时您正在尝试做什么?您的目标是运行命令还是打印一些东西?请在您的问题中添加更多详细信息,以便我们尝试帮助您,干杯。 edit 您的问题要包括该信息和所有其他信息,请勿将其放在无法格式化且容易遗漏的 cmets 中。此外,您在使用 awk 时永远不需要 sed,因此请确保向我们展示您想要的最终输出格式,而不是您当前认为需要运行 sed 的格式。一定要显示一个minimal reproducible example,例如每 3 行而不是 1000 行。 awk 'print $1' CatalogEntriesDescription.csv | split -l 1000? 这能回答你的问题吗? How can I split a large text file into smaller files with an equal number of lines? 您添加了代码,但仍然没有示例输入和预期输出,因此到目前为止您已经提供了我们要求您提供的三分之一,因此我们可以为您提供帮助。正如我在my first comment above 中提到的,一定要展示一个minimal reproducible example,其中包含简洁、可测试的样本输入和预期输出,例如例如,一个 10 行长的文件,例如,每 3 行而不是 1000 行被拆分。 【参考方案1】:

假设您的输入 CSV 的前两个字段是 "simple"(没有空格,没有逗号...)并且不需要任何类型的引用。您可以使用 awk 脚本生成查询字符串的棘手部分:

# foo.awk
NR >= first && NR <= last 
    c1[n+0] = $1
    c2[n++] = $2

END 
    for(i = 0; i < n-1; i++) printf("%s,", c1[i])
    printf("%s) %s (%s", c1[n-1], midstr, c2[0])
    for(i = 1; i < n; i++) printf(",%s", c2[i])

然后在bash 循环中使用它来处理每次迭代的 1000 条记录,将查询结果存储在一个临时文件中(例如,tmp.csv 在下面的bash 脚本中),你可以连接到你的@ 987654326@ 文件。以下示例bash 脚​​本使用与您相同的参数(INPUTsourceDBStr)和相同的常量(dbData.csv1000user123pas123)。如果您需要更大的灵活性,请进行调整。错误管理(未找到输入文件、DB 连接错误、DB 查询错误...)留作bash 练习(但应该完成)。

prefix="export to tmp.csv of del select partnumber,language_id as LanguageId from  CATENTRY c , CATENTDESC cd where c.CATENTRY_ID=cd.CATENTRY_ID and c.PARTNUMBER in"
midstr="and cd.language_id in"

rm -f dbData.csv
len=$(cat "$INPUT" | wc -l)
for (( first = 2; first <= len - 999; first += 1000 )); do
    (( last = len < first + 999 ? len : first + 999 ))
    query=$(awk -F ',' -f foo.awk -v midstr="$midstr" -v first="$first" \
      -v last="$last" "$INPUT")
    echo "Please wait - connecting to database..."
    db2 connect to $sourceDBStr user user123 using pas123
    db2 "$prefix ($query)"
    cat tmp.csv >> dbData.csv
done
rm -f tmp.csv

但还有其他方法可以使用 splitbash 数组和更简单的 awksed 脚本。示例:

declare -a arr=()
prefix="export to tmp.csv of del select partnumber,language_id as LanguageId from  CATENTRY c , CATENTDESC cd where c.CATENTRY_ID=cd.CATENTRY_ID and c.PARTNUMBER in"
midstr="and cd.language_id in"

awk -F, 'NR>1 print $1, $2' "$INPUT" | split -l 1000 - foobar

rm -f dbData.csv
for f in foobar*; do
  arr=($(awk 'print $1 ","' "$f"))
  i="$arr[*]"
  arr=($(awk 'print $2 ","' "$f"))
  j="$arr[*]"
  echo "Please wait - connecting to database..."
  db2 connect to $sourceDBStr user user123 using pas123
  db2 "$prefix ($i%,) $midstr ($j%,)"
  cat tmp.csv >> dbData.csv
  rm -f "$f"
done
rm -f tmp.csv

【讨论】:

以上是关于使用 awk 命令从 csv 读取和打印第一 1000 行,然后再打印 1000 行,依此类推的主要内容,如果未能解决你的问题,请参考以下文章

awk用法详解

Linux AWK学习

我正在使用awk命令,但无法使用shell脚本在列中打印IP

用awk如何读取shell命令行上的参数(参数可以是带空格的)

awk

如何从 CSV 文件中获取每一行的第一列?