我有一个名为myfile.csv
包含以下内容的文件:
abc:123:myname:1231
def:423324:arbitrary:value:string
StackExchange:Unix:Linux
从我运行的终端./myscript.sh def
的内容myscript.sh
是:
#!/bin/bash
key_word_I_am_looking_for=$1
my_variable=`cat myfile.csv | awk -F: -v keyword="$key_word_I_am_looking_for" '( $1 == keyword )' END{print "$@" }'`
echo "$my_variable"
我希望代码def
在myfile.csv
ieabc
或StackExchange
.一旦找到,我希望它在没有分隔符的情况下取出整行并将其放入变量中my_variable
,并将其回显到终端(因此输出将如下所示:def 423324 arbitrary value string
何时./myscript.sh def
输入到终端。何时./myscript.sh StackExchange
输出将是StackExchange Unix Linux
) 。
我哪里错了?还有其他选择吗?
答案1
你的 awk 语法有点错误。
#!/bin/bash
awk -F: -v keyword="$1" '$1 == keyword {$1=$1; print}' myfile.csv
这里的技巧是重新分配其中一个字段的值,强制 awk 使用输出文件分隔符重新计算 $0。这里,默认的 OFS 是一个空格,因此将 $1 的值分配给自身会将冒号更改为空格。
一种非 awk 的写法是:
grep "^$1:" myfile.csv | tr ":" " "
但这使用正则表达式匹配,而不是字符串相等
答案2
这是一个sed
替代方案:
sed -n '/^def:/s/:/ /gp' myfile.csv
如果将字符串作为第一个位置参数传递:
sed -n "/^$1:/s/:/ /gp" myfile.csv
答案3
通过蟒蛇。
$ python -c "import sys;
with open(sys.argv[2]) as f:
for line in f:
if sys.argv[1] == line.split(':')[0]:
print ' '.join(line.strip().split(':'))" def file
def 423324 arbitrary value string
只需在终端上运行上述脚本,将搜索关键字作为第一个参数,将文件名作为第二个参数。
答案4
使用 Raku(以前称为 Perl_6)
raku -ne '.put if .=split(":")[0] eq "def";' myfile.csv
输出:
def 423324 arbitrary value string
语言注释:Perl 系列语言利用“主题”变量的概念。 Raku 扩展并规范了这一概念(请参阅下面的 Rosetta 代码链接)。由于例程现在默认为$_
主题变量,因此只需一个前导句点即可指示操作在主题$_
变量。写出上面的代码“手写”,你实际上会得到:
raku -ne '$_.put if $_.=split(":")[0] eq "def";'
最后,Raku 提供了.=
二元赋值运算符,其中基本上=
只需要插入一个(等号)即可更新左值。因此代码my $temp = $_.fn(…); $_ = $temp;
可以被压缩为$_.=fn(…)
.更短...并且无需创建$temp
临时变量!
https://rosettacode.org/wiki/Topic_variable#Raku
https://docs.raku.org/routine/.=
https://raku.org/