mypath='my/path/to/version/5e/is/7/here'
我想要提取包含数字的第一个部分。例如,我想要提取:5e
是否有比使用while循环遍历每个部分并检查其中是否有数字更好的方法?
while IFS=/ read part
do
if [[ $part =~ *[0-9]* ]]; then
echo "$part"
fi
done <<< "$mypath"
使用 Bash 的正则表达式:
[[ "$mypath" =~ [^/]*[0-9]+[^/]* ]] && echo "${BASH_REMATCH[0]}"
5e
使用 'grep -o' 方法。
echo $mypath | grep -o -E '\b[^/]*[0-9][^/]*\b' | head -1
/
替换为换行符mypath='my/path/to/version/5e/is/7/here'
<<<"${mypath//\//$'\n'}" grep -m1 '[0-9]'
如果路径中包含换行符,则可以使用零分隔流和GNU工具作为更安全的替代方法:
<<<"${mypath}" tr '/' '\0' | grep -z -m1 '[0-9]'
有没有比使用while循环并检查每个部分是否为数字更好的方法?
没有,无论如何,您都必须遍历所有部分,直到发现第一个带数字的部分。循环可能隐藏在其他工具后面,但它仍将遍历各个部分。您的解决方案本身似乎非常不错,如果您只想要第一个部分,请在找到第一个部分后使用break
。
请尝试以下代码,已使用示例进行编写和测试。如果行中有多个值,则应打印此内容。如果要讨论更好的方法,awk
可能比纯 bash 循环 + 正则表达式解决方案更快,所以在此添加它。
awk -F'/' '
{
val=""
for(i=1;i<=NF;i++){
if($i~/[0-9][a-zA-Z]/ || $i~/[a-zA-Z][0-9]/){
val=(val?val OFS:"")$i
}
}
print val
}' Input_file
说明:为上述内容添加详细解释。
awk -F'/' ' ##Starting awk program from here and setting field separator as / here.
{
val="" ##Nullifying val here.
for(i=1;i<=NF;i++){ ##Running for loop till value of NF.
if($i~/[0-9][a-zA-Z]/ || $i~/[a-zA-Z][0-9]/){ ##Checking condition if field value is matching regex of digit alphabet then do following.
val=(val?val OFS:"")$i ##Creating variable val where keep on adding current field value in it.
}
}
print val ##Printing val here.
}' Input_file ##Mentioning Input_file name here.
mypath='my/path/to/version/5e/is/7/here'
# Method 1 (using for loop):
echo "${mypath}" | perl -F'/' -lane 'for my $dir ( @F ) { next unless $dir =~ /\d/; print $dir; last; }'
# Method 2 (using grep):
echo "${mypath}" | perl -F'/' -lane 'my $dir = ( grep { /\d/ } @F )[0]; print $dir if defined $dir;'
# Prints:
# 5e
这个 Perl 一行命令使用了以下命令行标志:
-e
:告诉 Perl 在行内查找代码,而不是在文件中。
-n
:逐行循环输入,将其默认赋值给 $_
。
-l
:在执行行内代码之前剥离输入行分隔符(默认为 *NIX 上的 "\n"
),并在打印时附加它。
-a
:在空格或 -F
选项指定的正则表达式上将 $_
分割成数组 @F
。
-F'/'
:在 /
上分割为 @F
,而不是在空格上。
next unless $dir =~ /\d/;
:如果路径的当前部分不包含数字(\d
),则跳过循环的其余部分。
last;
:退出循环(在这里也退出脚本),以便仅打印匹配目录的第一个实例。
grep { ... } LIST
:对于LIST
参数,返回表达式...
为真的元素列表,在此处返回具有数字的所有路径元素列表。
(LIST)[0]
:返回LIST的第一个元素,在此处为具有数字的第一个路径元素。
另请参阅:
perldoc perlrun
: 如何执行Perl解释器:命令行开关
awk
,将 RS
设置为 /
并打印第一个包含数字的记录。awk -v RS=/ '/[0-9]/{print;exit}' <<< "$mypath"
5e
另一种Bash变体
mypath='my/path/to/app version/5e/is/7/here'
until [[ ${mypath:0:1} =~ [0-9] ]]; do
mypath=${mypath#*/}
done
echo ${mypath%%/*}