1

我目前正在编写一个重新排列 csv 文件内容的脚本。如果我有与此类似的行:

stack,over,flow,dot,com

我该如何确定命令分隔字符串中字符串/单词的位置。因此,例如,如果我要搜索堆栈,它将返回数字 1,如果我要搜索流,则将返回数字 3,依此类推。我已经想到了几种方法可以做到这一点,但它们大多是冗长的脚本,所以我觉得可能有一种更短/更简单的方法来做到这一点。如果有人可以提供建议/帮助,我将不胜感激,谢谢。这也是在 bash 环境中执行的

4

8 回答 8

3

awk oneliner:

awk -F, -vs=$search '{for (i=1;i<=NF;i++)if($i~"^"s"$"){print i;exit;}}{print "not found"}' yourString

(see the example test below)

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
于 2012-11-12T16:38:19.783 回答
2
echo $line | awk -F, '{
  for(i=1;i<=NF;i++){
    if($i=="your_string") print i;
  }
}'

Note: NF stands for Number of Fields.

于 2012-11-12T16:38:51.147 回答
1

一个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
于 2012-11-12T17:33:34.627 回答
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]}"
于 2012-11-13T03:54:05.487 回答
0

sed and grep represented so far. Here's an awk solution:

echo "stack,over,flow,dot,com" | awk -F, '{ for (i=1; i < NF; ++i) if ($i == "flow") print i; }'
于 2012-11-12T16:40:50.990 回答
0

分割线,然后找到行号

您可以使用 sed 拆分行,然后找到匹配的行号。例如:

search_term='flow'
echo 'stack,over,flow,dot,com' |
    sed -e  's/,/\n/g' |
    sed -ne "/^${search_term}\$/ {=; q}"

因为 sed 是面向行的,所以在搜索匹配的行号之前需要先转换整个文件。这就是为什么我们要传递到另一个 sed 实例,而不是简单地在当前进程中使用第二个表达式。

当然还有其他方法可以做到这一点,但这更容易。YMMV。

于 2012-11-12T16:32:58.680 回答
0

假设您要查找所有单词:

$ 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
于 2012-11-13T01:52:38.563 回答
0

您可以将逗号计数到匹配的字符串:

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将是可行的方法。

于 2012-11-12T16:25:41.863 回答