bash 如何获取匹配的行号?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/31431991/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 13:20:26  来源:igfitidea点击:

How to get the line number of a match?

bashgreppattern-matchingstring-split

提问by Jérémy

My aim is to get the line number ($lineof) of a string which matches a line in /etc/crontab.

我的目标是获取与/etc/crontab.

To give 0 8 * * * Me echo "start working please"and get this is the line number 13 from /etc/crontab.

给予0 8 * * * Me echo "start working please"和得到this is the line number 13 from /etc/crontab

Given this file /tmp/crontab:

鉴于此文件/tmp/crontab

# /etc/crontab: system-wide crontab
# Unlike any other crontab you don't have to run the `crontab'
# command to install the new version when you edit this file
# and files in /etc/cron.d. These files also have username fields,
# that none of the other crontabs do.

SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

# m h dom mon dow user  command
#
0 17 * * * Me echo "end of work"
0 8 * * * Me echo "start working please"
1 3 2 4 2 Me ls -la

I do something like that for the moment:

我暂时做这样的事情:

cat /etc/crontab | grep -v "#" | grep "Me" > /tmp/task.cron
i=1
while read -r content
do
        line=$content
        # lineof=$LINENO
        nbline=${i}
        minute=$(echo "$line" | awk '{print }')  #0-59
        hour=$(echo "$line" | awk '{print }')    #0-23
        dom=$(echo "$line" | awk '{print }')     #1-31
        month=$(echo "$line" | awk '{print }')   #1-12
        dow=$(echo "$line" | awk '{print }')     #0-6 (0=Sunday)
        cmd=$(echo "$line" | awk '{======""; print 
grep -Fn 'your_line' /etc/crontab
}') #command cmd=$(echo "$cmd" | tr ' ' _) str=$str' '$nbline' "'$minute'" "'$hour'" "'$dom'" "'$month'" "'$dow'" "'$user'" "'$cmd'" ' i=$(($i+1)) done < /tmp/task.cron

$nblinegive me the line of the content in /tmp/task.cron

$LINENOgive me the line of the current script (which execute the program)

I want $lineofgive me the number of the line in /etc/crontab

$nbline给我/tmp/task.cron中的内容

$LINENO给我当前脚本的行(执行程序)

我想$lineof给我/etc/crontab中的行号

采纳答案by fedorqui 'SO stop harming'

To print the line number of your match, use the -noption of grep. Since the pattern contains some special characters, use -Fto make them be interpreted as fixed strings and not a regular expression:

要打印匹配的行号,请使用-n选项grep。由于模式包含一些特殊字符,使用-F使它们被解释为固定字符串而不是正则表达式:

awk -v line='your_line' '
$ cat a
# /etc/crontab: system-wide crontab
# Unlike any other crontab you don't have to run the `crontab'
# command to install the new version when you edit this file
# and files in /etc/cron.d. These files also have username fields,
# that none of the other crontabs do.

SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

# m h dom mon dow user  command
#
0 17 * * * Me echo "end of work"
0 8 * * * Me echo "start working please"
1 3 2 4 2 Me ls -la
== line {print "this is the line number", NR, "from", FILENAME}' /etc/crontab

However, since you want to print some message together with the line number, you may want to use awkinstead:

但是,由于您想与行号一起打印一些消息,您可能需要使用awk

$ awk -v line='0 8 * * * Me echo "start working please"' '
$ grep -Fn '0 8 * * * Me echo "start working please"' a13:0 8 * * * Me echo "start working please"
13:0 8 * * * Me echo "start working please"
== line {print "this is the line number", NR, "from", FILENAME}' a this is the line number 13 from a

Test

测试

nbline=1
        while read -r content
        do
                line=$content
                if [ "${line:0:1}" != "#" ]; then #if this is not a comment
                        line=$(echo -e "$line" | grep "$user") #$line keep only lines with the $user choose
                        if [ ! -z "$line" ];then #if this is not a void $line
                                minute=$(echo -e "$line" | awk '{print }') #0-59
                                hour=$(echo -e "$line" | awk '{print }')   #0-23
                                dom=$(echo -e "$line" | awk '{print }')    #1-31
                                month=$(echo -e "$line" | awk '{print }')  #1-12
                                dow=$(echo -e "$line" | awk '{print }')    #0-6 (0=Sunday)
                                cmd=$(echo -e "$line" | awk '{======""; print ##代码##}')    #command
                                cmd=$(echo -e "$cmd" | tr ' ' _) #replace space by '_' because it's annoying later
                                str=$str' "'$nbline'" "'$minute'" "'$hour'" "'$dom'" "'$month'" "'$dow'" "'$user'" "'$cmd'" '
                        fi
                fi
                nbline=$(($nbline+1))
        done < /etc/crontab

With awk:

awk

##代码##

With grep:

grep

##代码##

回答by Jérémy

I finally did like this, found alone :

我终于这样做了,独自发现:

##代码##

I don't need to create an other file and get in $nbline the number of current line in loop. And count all line, even if they are void or commented. That's what I wanted.Gcron: a graphical preplanned task manager.

我不需要创建其他文件并在 $nbline 中获取循环中当前行的数量。并计算所有行,即使它们是无效的或注释的。这就是我想要的。Gcron:图形化的预先计划的任务管理器。

'#' is the line number of the right content in /etc/crontab.

'#' 是 /etc/crontab 中正确内容的行号。