如何在Shell中的另一个字符串中获取字符串的行号

如何在Shell中的另一个字符串中获取字符串的行号,shell,awk,grep,Shell,Awk,Grep,给定 我想获取$sourceStr中第一次出现的$str的行号,它应该是3 我不知道怎么做。 我试过: str="hij"; sourceStr="abc\nefg\nhij\nlmn\nhij"; awk'match($0,v){print NR;exit}'v=$str您可以在bash中使用此awk+printf: awk-v s=“$str”'$0==s{print NR;exit}'不清楚您是否刚刚发生剪切粘贴错误,但您的sourceStr不是多

给定

我想获取
$sourceStr
中第一次出现的
$str
的行号,它应该是
3

我不知道怎么做。 我试过:

str="hij";
sourceStr="abc\nefg\nhij\nlmn\nhij";

awk'match($0,v){print NR;exit}'v=$str您可以在
bash
中使用此
awk+printf


awk-v s=“$str”'$0==s{print NR;exit}'不清楚您是否刚刚发生剪切粘贴错误,但您的
sourceStr
不是多行字符串(如下所示)。另外,您确实需要引用您的herestring(也在下面演示)。也许你只是想:

awk 'match($0, v) { print NR; exit }' v=$str <<<$sourceStr
grep -n $str <<< $sourceStr | grep -Eo '^[^:]+';
grep -n $str <<< $sourceStr | cut -f1 -d: | sort -ug
grep -n $str <<< $sourceStr | awk -F: '{ print $1 }' | sort -u
$sourceStr=“abc\nefg\nhij\nlmn\nhij”
$echo“$sourceStr”
abc\nefg\nhij\nlmn\nhij
$sourceStr=$'abc\nefg\nhij\nlmn\nhij'
$echo“$sourceStr”
abc
efg
你好
lmn
你好

$cat要做到这一点,总有一个艰难的方法:

str=“hij”;
sourceStr=“abc\nefg\nhij\nlmn\nhij”;
echo-e$sourceStr | nl | grep$str | head-1 | gawk'{print$1}'
或者,更有效一点:

str=“hij”;
sourceStr=“abc\nefg\nhij\nlmn\nhij”;
echo-e$sourceStr | gawk'/'$str/'{print NR;exit}'

只需使用
sed

$ sourceStr="abc\nefg\nhij\nlmn\nhij"
$ echo "$sourceStr"
abc\nefg\nhij\nlmn\nhij
$ sourceStr=$'abc\nefg\nhij\nlmn\nhij'
$ echo "$sourceStr"
abc
efg
hij
lmn
hij
$ cat <<< $sourceStr 
abc efg hij lmn hij
$ cat <<< "$sourceStr" 
abc
efg
hij
lmn  
hij
$ str=hij
$ awk "/${str}/ {print NR; exit}" <<< "$sourceStr"
3
说明:如果
sed
遇到包含“hij”的行(regex
/hij/
),它将打印行号(
=
命令)并退出(
q
命令)。否则它将不打印任何内容(使用
-n
开关)并继续下一行


[更新]嗯,对不起,我刚刚注意到你的“所有输出1,而不是3”

命令不输出3的主要原因是
sourceStr=“abc\nefg\nhij\nlmn\nhij”
不会自动将
\n
更改为新行,因此它只显示一行,这就是为什么命令总是显示
1

如果您想要一个多行字符串,下面是使用
bash
的两种解决方案:

  • printf-v sourceStr“abc\nefg\nhij\nlmn\nhij”
  • sourceStr=$'abc\nefg\nhij\nlmn\nhij'
现在,正如William Pursell所说,变量包含空格字符(新行),为了保留它们,必须用双引号括住
$sourceStr

printf 'abc\nefg\nhij\nlmn\nhij\n' \
| sed -n '/hij/ { =; q; }'


grep-n“$str”您多次创建了一个变量,该变量包含一行文字字符串
\n
。您打算将
sourceStr
作为多行字符串吗?您想要字符串比较还是正则表达式比较?您好@williampersell,我的意思是多行字符串。我以为Shell会将其解释为多行字符串。谢谢你指出并给出答案。今天我学到了一些新东西!嗨@EdMorton,我如何实现目标并不重要。我只是想得到源字符串中匹配行的行号。对,我的问题是-目标是什么?是进行字符串比较还是正则表达式比较?例如,如果
v
a.c
,那么它应该只匹配输入中的
a.c
(与字符串比较一样),还是也应该匹配
abc
(与regexp比较一样)?有关不同类型比较的更多信息,请参阅。
/hij/
将在
@hijkl
中找到
hij
=
是safer@anubhava同意,但是OP使用了
match($0,v)
,所以这只是在模拟。但我相信这里的关键问题是字符串的赋值,而不是awk。在任何脚本或字符串周围使用双引号会打开一个蠕虫程序罐,以确保健壮性和安全性。您好@williampersell,感谢您向我展示这一点。我根本不知道这件事。因此,这两个函数都将输出相同的结果:``sourceStr=$“abc\nefg\nhij\nlmn\nhij”;echo$sourceStr sourceStr=“abc\nefg\nhij\nlmn\nhij”;echo“$sourceStr”``但是,这将输出
1
:``str=hij;sourceStr=$“abc\nefg\nhij\nlmn\nhij”;awk“/${str}/{print NR;exit}”对不起。编码的格式不好。按Enter键不能更改行。我不得不使用“Shift+Enter”来创建新行。但是,它们没有反映在注释中。
'/'$str/'..'
$str
暴露在shell中,用于全局绑定、工作拆分等。因此,它很脆弱,存在安全问题。要安全地做到这一点,需要使用“
”/“$str”/“…”
,但这仍然存在其他问题,因此千万不要让shell变量扩展为awk脚本文本的一部分,请参阅以获取详细信息
echo-e$sourceStr
grep$str
也应该是
echo-e“$sourceStr”
grep“$str”
顺便说一句-请查看shellHi@Luuk中何时可以安全/适当地删除引号,谢谢您的回复。奇怪的是,为什么代码不需要双引号来解释
\n
符号。我对安全问题知之甚少。然而,既然@EdMorton提到了这一点,我认为在你回答之前最好不要投票支持你的答案。再次感谢!由于echo之后的
-e
,因此解释了
\n
。(是的,埃德是对的!)嗨@anubhava,是的。他们都在Mac上的Terminal.app中工作。当我尝试在键盘大师中使用EXECUTEASHELL脚本时,只有最后一个有效。我收到一个错误报告:意外标记“(”)附近出现语法错误。但这没问题。我只需要一个有效的!感谢您提供这么多解决方案,以便我可以从中选择!
printf“%b\n”$sourceStr”| awk-v s=“$str”'$0==s{print NR;exit}“
应该也能工作Hi@anubhava,完成了!谢谢!Hi@xhiene,谢谢你的详细解释。你指出了我的代码与@williampershell指出的问题相同。我在Terminal.app中尝试了你的命令,但它不起作用。它给出了一个错误代码:
sed:1:/hij/{=;q}”:q命令末尾有额外字符
。我没有看到任何额外字符,因此我不知道发生了什么。嗯,对不起,我忘记了命令分隔符
。答案已更新。谢谢
grep -n "$str" <<< "$sourceStr" | ...