我有一个CSV文件grep
,其中的列数可能会有所不同,例如:
$ grep -v 'Coba' ETFs.csv | grep 'Sector'
CAPE,Ossiam Shiller Barclays Cape Europe Sector Value TR,EUPE,FWB
EUPB1,Ossiam Shiller Barclays Cape Global Sector Value,EUPB,FWB
对于grep的每一个输出行,我需要运行一个Python脚本,并提交带有-t
标志的列#3和带有-n
标志的列#2。为了简单起见,让我们假设脚本打印提交的参数。因此,在接收到上面的输出时,脚本应该像这样执行两次:
script.py -t EUPE -n Ossiam Shiller Barclays Cape Europe Sector Value TR
script.py -t EUPB -n Ossiam Shiller Barclays Cape Global Sector Value
我的问题是xargs
将整个grep
输出作为一个参数处理。预期的行为是逐行处理输入,按逗号分割行内容并以任何期望的顺序将其提交给脚本。如何做到这一点?
Python脚本示例:
import argparse, sys
aparser = argparse.ArgumentParser()
aparser.add_argument('-t', '--ticker', required=True)
aparser.add_argument('-n', '--name')
args = aparser.parse_args()
print(f"START {sys.argv[0]} for {args.ticker} {args.name}: ", end='')
更新23.3
目前的做法是只提交一个参数作为代码标志-t
,因为-n
名称标志是可选的。然而,真实的情况是一次提交多个标志,例如ETF代码和名称,筛选器,交易所等。
$ grep -v 'Coba' ETFs.csv | grep 'Sector' | cut -d ',' -f3 | xargs -I {} python script.py -t {}
正如评注中指出的,它也可以用awk
表示。
$ awk -F, '! /Coba/ && /Sector/ {print $3}' ETFs.csv | xargs -I {} python script.py -t {}
@SHERLOCK建议的解决方案其实看起来很有逻辑,我们提取了同一个输入的不同部分,但是第二次参数提交不起作用,导致argparse
使用提醒。
awk -F, '! /Coba/ && /Sector/ {printf "%s,%s\n", $3, $2}' ETFs.csv | xargs -t -I {} bash -c 'python script.py -t $(echo "{}" | awk -F "," "{print \$1}") -n $(echo "{}" | awk -F "," "{print \$2}")'
像rm -rf
这样的有害代码注入在这里不应该引起关注,因为我总是从检查CSV输出开始,然后才将其传输到脚本。
2条答案
按热度按时间voase2hg1#
BashFAQ #1
while read
循环比xargs
更好:这样我们就不会在每一行都启动一个单独的shell,而只是使用同一个shell,它已经在Python的awk的stdout上运行了脚本循环。因此,安全问题和引用错误都得到了解决。
一些注意事项:
script.py
可以使用它来提示用户,而不会无意中从ETFs.py
阅读数据。col2
之后的_
导致后续字段被丢弃(放入变量_
中,这是脚本中用于忽略垃圾的常规方法),而不是附加到col 2中的值。while read ...; done < <(awk ...)
而不是awk ... | while read ...; done
。"$(...)"
,而不仅仅是裸$(...)
,防止将结果字符串中的单词拆分为单独的参数(然后根据当前工作目录中的文件系统内容展开为globs)。因为第二列中的ETF描述包含空格,所以这对该数据至关重要。2mbi3lxu2#
您可以使用'-d'标志和xargs将分隔符指定为',',并使用'-I'标志为输入字符串指定占位符。之后,您可以使用'awk'从每行中提取所需的列,并将它们作为参数传递给Python脚本。
以下是您可以执行的操作:
这将用','分割每一个输入行,然后使用awk提取第三列和第二列,并将它们作为参数传递给script.py。第二列用双引号括起来,以处理包含空格的情况。
您可能需要根据您的shell和CSV文件的确切格式稍微修改该命令。