我目前正在处理一个脚本,该脚本将重新排列csv文件的内容。 如果我有一行类似于这样:
stack,over,flow,dot,com
我如何确定命令分隔字符串中字符串/单词的位置。因此,例如,如果我要搜索堆栈,它将返回数字 1,如果我要搜索流,将返回数字 3,依此类推。我已经想到了几种可以做到这一点的方法,但它们大多是冗长的脚本,所以我觉得可能有更短/更简单的方法可以做到这一点。如果有人可以提供建议/帮助,我将不胜感激,谢谢。这也是在 bash 环境中执行
awk oneliner:
awk -F, -vs=$search '{for (i=1;i<=NF;i++)if($i~"^"s"$"){print i;exit;}}{print "not found"}' yourString
(请参阅下面的示例测试)
kent$ l="stack,over,flow,dot,com"
kent$ echo $l
stack,over,flow,dot,com
kent$ search=over
kent$ echo $search
over
kent$ awk -F, -vs=$search '{for (i=1;i<=NF;i++)if($i~"^"s"$"){print i;exit;}}{print "not found"}' <<<$l
2
kent$ search=foobar
kent$ awk -F, -vs=$search '{for (i=1;i<=NF;i++)if($i~"^"s"$"){print i;exit;}}{print "not found"}' <<<$l
not found
echo $line | awk -F, '{
for(i=1;i<=NF;i++){
if($i=="your_string") print i;
}
}'
注意:NF 代表字段数。
一个bash函数:
position() {
local search=$1
local IFS=,
local i=1
set -- $2
for word; do
if [[ $word = $search ]]; then
echo $i
return
fi
((i++))
done
echo -1
}
然后:
$ position stack stack,over,flow,dot,com
1
$ position tack stack,over,flow,dot,com
-1
仅仅因为你要求一个 100% bash 解决方案(这不使用 sed、awk、seq 等):
L='stack,over,flow,dot,com'
IFS=,
set -- $L
declare -A A
for ((i=1; i<=$#; i++))
do
A[${!i}]=$i
done
# where's flow?
echo "flow=${A[flow]}"
您可以将逗号数到匹配的字符串:
for word in stack over flow dot com ; do
echo $word
grep -o ".*$word" <<< stack,over,flow,dot,com
| grep -o ,
| wc -l
done
但是如果你想用CSV做更多的操作,切换到Perl并使用Text::CSV将是要走的路。
拆分行,然后查找行号
您可以使用 sed 拆分行,然后找到匹配的行号。例如:
search_term='flow'
echo 'stack,over,flow,dot,com' |
sed -e 's/,/n/g' |
sed -ne "/^${search_term}$/ {=; q}"
由于 sed 是面向行的,因此在搜索匹配的行号之前,必须先转换整个文件。这就是为什么我们要管道到sed的另一个实例,而不是简单地在当前进程中使用第二个表达式。
当然还有其他方法可以做到这一点,但这更容易。扬子晚报.
sed
和grep
表示。这是一个awk
解决方案:
echo "stack,over,flow,dot,com" | awk -F, '{ for (i=1; i < NF; ++i) if ($i == "flow") print i; }'
假设您要查找所有单词:
$ LINE=stack,over,flow,dot,com
$ read ${LINE//,/ } rest < <(echo $(seq 100))
$ echo $stack $over $flow $dot $com
1 2 3 4 5
当然,这很容易给您带来名称冲突,因此您可能希望在名称中添加一些前缀:
$ LINE=stack,over,flow,dot,com
$ read field_${v//,/ field_} rest < <(echo $(seq 100))
$ echo $field_stack $field_over $field_flow $field_dot $field_com
1 2 3 4 5