给定line
,delimiter
和word
,我想根据分隔符获得该词在行中的索引位置。尽可能简单/简短。所以对于:
line="this-is-a-line_with-some.txt"
delimiter="-"
word="some"
echo <code goes here>
# should come out as 4
当然,我可以用一个数组拆分它,并使用for循环打印第一次出现的单词,如下所示:
line="this-is-a-line_with-some.txt"
delimiter="-"
word="some"
index=0
IFS="$delimiter" read -ra ary <<<"$line"
for i in "${ary[@]}"; do
if [[ $i == ${word}* ]]; then echo $index ; break ; fi
index=$((index+1))
done
但我肯定有一个更简单的解决办法。
simple解决方案。
用换行符替换分隔符,用grep获取行号。
<<<"$line" tr "$delimiter" 'n' | grep -n "$word" | cut -d: -f1
- 1:
<<<"$line" tr "$delimiter" 'n' | grep -n "$word" | cut -d: -f1 | awk '{print $1 - 1}'
# shorter
<<<"$line" tr "$delimiter" 'n' | grep -n "$word" | awk -F: '{print $1-1}'
或者直接awk:
<<<"$line" awk -v RS="$delimiter" -v word="$word" '$0 ~ word{print NR-1}'
从OP的代码和/或注释中理解:
- 查找第一个出现以
${word}
开头的 - 位置索引以0为基础 如果没有找到
${delimiter}
分隔字段${word}
,则生成no输出OP的代码可以通过使用数组的基于0的索引进一步减少(即,消除对index
变量的需要):
IFS="$delimiter" read -ra ary <<<"$line"
for i in "${!ary[@]}"
do
[[ "${ary[i]}" == ${word}* ]] && echo "${i}" && break
done
# line="this-is-a-line_with-some.txt"
4
# line="a-some_def-xy-some.pdf"
1
注意:如果没有找到${word}
,这将生成no输出
来自superuser的参数替换解决方案的变化:
newline="${line%%${word}*}" # truncate string from 1st occurrence of ${word}
if [[ "${newline}" != "{line}" ]] # if strings are different then we found ${word}
then
IFS="${delimiter}" words_before=( ${newline} ) # break remaining string by "${delimiter}" and
# store in array words_before[]
echo "${#words_before[@]}" # number of array entries == index of 1st occurrence of ${word}
fi
# line="this-is-a-line_with-some.txt"
4
# line="a-some_def-xy-some.pdf"
1
注意:如果没有找到${word}
,这将生成no输出
一个awk
的想法:
awk -F"${delimiter}" -v ptn="${word}" '{for (i=1;i<=NF;i++) if (index($i,ptn) == 1) {print i-1; exit}}' <<< "${line}"
# line="this-is-a-line_with-some.txt"
4
# line="a-some_def-xy-some.pdf"
1
或者使用内联替换ptn/${word}
:
awk -F"${delimiter}" '{for (i=1;i<=NF;i++) if ($i ~ /^'"${word}"'/) {print i-1; exit}}' <<< "${line}"
# line="this-is-a-line_with-some.txt"
4
# line="a-some_def-xy-some.pdf"
1
注意:如果没有找到${word}
,这些awk
脚本将生成no输出
要获得真正最短代码的想法,OP可以尝试发布@ codegolf,尽管真正简短的答案可能需要定位/安装新软件(库和/或二进制文件)
无需循环或外部工具的解决方案:
line="$delimiter$line"; lin2="${line%$delimiter$word*}"
if test "$lin2" != "$line"; then
IFS="$delimiter" read -ra ary <<<"${lin2#$delimiter}"
echo ${#ary[@]}
fi