如何使用 sed 根据第 1 列和第 7 列中的模式过滤 csv 文件的结果?

如何使用 sed 根据第 1 列和第 7 列中的模式过滤 csv 文件的结果?

我正在尝试编写一个 shell 脚本,扫描第 1 列和第 7 列中用户指定的值,其中 $3 与第 7 列中匹配,$2 与第一列中匹配的年份($1 是文件名)。我可以很好地匹配第七列,但在尝试添加要在第一列中匹配的变量时,不断收到错误 'sed: -e expression #1, char 7:unknown command: `2' 。不幸的是,我必须使用 sed 而不是 awk。到目前为止,这是我所拥有的:

sed -n "/"$2",[^,],[^,],[^,],[^,],[^,]*,"$3"/p" "$1"

我应该怎么解决这个问题?我是一个新手,所以欢迎所有帮助。尝试过 shellcheck 但没有帮助。该脚本在扫描第 7 列时运行良好,但添加 $2 方面会导致错误。

编辑:示例调用:

./script.sh filename "2015.2016" "South"

示例文件(“...”是内部有文本的列):

2021/2022,text,text,text,text,text,South,text,...,...
2021/2022,text,text,text,text,text,North,text,...,...
2015/2016,text,text,text,text,text,South,text,...,...
2014/2015,text,text,text,text,text,West,text,...,...

预期输出:

2015/2016,text,text,text,text,text,South,text,...,...

编辑:虽然我同意它确实不是这项工作的最佳工具,但我在玩了一下之后想出了如何使用 sed 来完成此任务:

#!/bin/bash

year="$2"
name="$3"

sed -n '/^'"$year"',\([^,]*,\)\{5\}'"$name"'\(,.*\)\{0,\}$/p' "$1" 

不知道我是否会使用它,但也许它会帮助其他人。请注意,输入需要一个“.”而不是“/”,以便产生准确的结果。

答案1

sed 不是一个很好的工具,只需使用 awk:

$ cat script.sh
#!/usr/bin/env bash

awk -F',' '$1==a && $7==b' a="$2" b="$3" "$1"

$ ./script.sh file.csv "2021" "South"
2021,text,text,text,text,text,South,text

不过,由于您需要 sed 解决方案,因此使用 POSIX sed:

$ cat script.sh
#!/usr/bin/env bash

a=$(sed 's/[^^\\]/[&]/g; s/\^/\\^/g; s/\\/\\\\/g' <<< "$2")
b=$(sed 's/[^^\\]/[&]/g; s/\^/\\^/g; s/\\/\\\\/g' <<< "$3")
sed -n '/^'"$a"',\([^,]*,\)\{5\}'"$b"'\(,.*\)\{0,\}$/p' "$1"

$ ./script.sh file.csv "2021" "South"
2021,text,text,text,text,text,South,text

是否可以使用 sed 可靠地转义正则表达式元字符为什么前两个 sed 命令是必要的,但简而言之,这是因为您需要进行文字字符串匹配,而 sed 仅支持正则表达式匹配,而不支持文字字符串匹配,因此您必须转义每个可能的正则表达式元字符(实际上您必须转义每个char ,因为任何 char 都可以是 sed 脚本分隔符,例如/) ,使其表现得像文字字符一样。这是第二个重要线索,表明 sed 是不适合这项工作的工具(第一个是它不会将输入拆分为字段),而不是像 awk 这样只支持文字字符串匹配的工具。

相关内容