【问题标题】:Utilizing awk/sed to print fields within a given csv in Bash在 Bash 中使用 awk/sed 打印给定 csv 中的字段
【发布时间】:2020-06-22 10:53:25
【问题描述】:

我正在尝试使用 awk/sed 的组合来打印给定 csv 中的某些字段。我在让 awk 识别代​​码中的给定参数(例如 ./printcsv.sh 3 5 - 参数为 3 和 5 并尝试通过 awk 打印 csv 的第 3 和 5 列)时遇到问题。

#! /bin/bash

read -p "What file would you like to print? " file
read -p "What directory is this file located in? " directory

cd $directory

touch readcsv.txt

for (( i = 1; i <= $#; i=i+1 ))
    do
        cat $file | awk -F "," -v var=${i} 'NR==2 {print $var }' "$directory"/"$file" >> readcsv.txt

    done

cat readcsv.txt

rm readcsv.txt

我已经考虑或创建了一个临时 .txt 文件,我会将打印的字段附加到其中,以便找到要读取的 .txt 文件,但我遇到了麻烦(可能是因为缺乏相关知识sed)在文件中创建一个表,因为输出只是紧挨着的两列(一个非常长的列)。另外,我不知道问题是否在于我创建的“for”循环,或者我试图扩展变量“i”的方式,但即使我将参数设置为 3 和 5,我的希望是 $1 然后将转换为参数 3(因此 csv 中的第 3 列),而不是它仍然转换为 awk 命令中的第 1 列。

作为一个参考框架,我对 Bash 很陌生,都是通过在线课程自学的,只有在你接触到非课程示例之前,这才有很大帮助。

【问题讨论】:

  • wrt I am trying to utilize a combination of awk/sed - 当你使用 awk 时,你永远不需要 sed。您应该通过 shellcheck(例如 shellcheck.net)运行您的代码并阅读 why-is-using-a-shell-loop-to-process-text-considered-bad-practicemywiki.wooledge.org/Quotesporkmail.org/era/unix/award.html
  • 虽然下面的答案向您展示了如何有效地完成您的任务,但您可能仍然想了解如何循环命令参数。那么${i}$i 相同,它扩展为迭代变量i 的值。如果您确实想扩展至第 i 个位置参数,则必须使用 ${!i} 添加一个间接级别。如果您只需要参数值,没有索引,那么您可以使用更简单的语法for arg in "$@"; do echo doing something with arg "$arg"...; done

标签: linux bash csv awk sed


【解决方案1】:

print columns 3 and 5 of a csv via awk,这就是你所需要的:

num1=3
num2=5

awk -v list="$num1 $num2" '
    BEGIN {
        n = split(list,cols)
        FS=OFS=","
    }
    {
        for (i=1; i<=n; i++) {
            printf "%s%s", $(cols[i]), (i<n ? OFS : ORS)
        }
    }
' file

而且,如果您愿意,从 3 打印到 5 将是:

awk -v beg="$num1" -v end="$num2" '
    BEGIN {
        FS=OFS=","
    }
    {
        for (i=beg; i<=end; i++) {
            printf "%s%s", $i, (i<end ? OFS : ORS)
        }
    }
' file

以上假设您有一个非常简单的 CSV,否则请参阅whats-the-most-robust-way-to-efficiently-parse-csv-using-awk

【讨论】:

    【解决方案2】:

    尝试使用内置插件,然后再推出自己的插件。

    例如,cut 已经可以满足您的需求

    $ cut -d, -f3,4,5 file
    

    如果脚本输入参数是“3,4,5”,你可以在你的脚本中使用这个

    cut -d, -f"$@" "$file"
    

    将显示选定的列,无需创建临时文件。附带的好处是,它也支持范围,因此您也可以使用“3-5”输入格式。

    【讨论】:

      猜你喜欢
      • 2019-04-04
      • 1970-01-01
      • 1970-01-01
      • 2013-01-06
      • 2017-01-16
      • 2016-12-11
      • 1970-01-01
      • 1970-01-01
      • 2013-01-07
      相关资源
      最近更新 更多