如何为 psql 输出中存在的值 grep 外壳变量?



以下是我正在尝试做的事情的简短摘要:

假设我有一个 CSV 作为 $variable 存储在外壳中。它看起来像这样:

account,index,quantity
100,AAPL,10
105,NFLX,25
110,TSLA,50
120,TWTR,45

现在我从外壳查询一个 PSQL 数据库,如下所示:

accounts=$(psql -d mydb -h mydb -f "SELECT account_num FROM accounts WHERE is_relevant")

现在我有一个帐户列表,存储在一个看似非结构化的变量中。简单地说,我想过滤原始CSV以获取新帐户查询中给出的值。

1(当我在存储查询结果的变量上调用echo时,我得到了一长串输出 - 只是所有相关帐户的串联列表。

2(当我在变量上调用head时,每个帐号都会抛出一个错误:

head: cannot open '100' for reading: No such file or directory

我看到这个,我认为,"shell 没有将这些条目识别为要打印的字符串,而是要运行的命令" - 我不确定如何解决这个问题。尝试使用 sed 放置引号或逗号来分隔字符串会引发类似的错误 - 关于丢失文件或不存在的命令。

虽然我怀疑 grep 最终是正确的工具 - 我想开放式地提出这个问题。你会怎么做?

编辑:澄清,鉴于我的原始帐户表,如果 PSQL 查询返回:

100
105
120

我想根据这些值过滤原始表,以获得:

account,index,quantity
100,AAPL,10
105,NFLX,25
120,TWTR,45

(帐户 # 110 的行已被过滤掉。

您可以在查询后尝试此操作:

# Create a filtered_variable to store the filtered results
# and add the first line from the original variable (the CSV header)
filtered_variable=$(echo "$variable" | head -n 1)
# For each account in the accounts obtained in the query
for account in $accounts
do
# Create a filtered_line variable to store the line where the account
# appears in the CSV, or an empty line if the account is not in the CSV
filtered_line=$(echo "$variable" | grep "^$account,")
# If $filtered_line is not empty (the account is in the CSV) ...
if [ ! -z "$filtered_line" ]
then
# ... add the line to the filtered_variable (filtered CSV)
filtered_variable+=$'n'"$filtered_line"
fi
done

现在,您在变量filtered_variable中拥有过滤后的表。如果你想在原始variable中使用它,那么只需在循环后执行variable="$filtered_variable"即可。

替代解决方案

您还可以将egrep与包含查询中返回的所有帐户的正则表达式一起使用。例如

echo "$variable" | egrep -e "^100,|^110,"

会回来

100,AAPL,10
110,TSLA,50

此正则表达式查找以100,110,开头的行。我添加了,以避免错误的可能匹配。

因此,您所需要的只是为查询中返回的所有帐户创建该正则表达式。这可以通过sed轻松完成:

filter=$(echo "^$accounts," | sed -e 's/ /,|^/g')

现在你有你的过滤器作为变量filter中的正则表达式,剩下的就是做egrep

filtered_variable=$(echo "$variable" | egrep "$filter")

同样,您将在辅助变量filtered_variable中拥有过滤后的帐户(不要忘记先添加CSV标题行(。

最新更新