Maneira de linha de comando para visualizar uma linha de um arquivo com contexto?

0

Gostaria de mostrar uma certa linha ou linhas de um arquivo com contexto, como uma diff unificada, na linha de comando do Linux:

$ (something) -l 154 stuff.py

   150:  def foo(bar):
   151:    """
   152:    Does the thing.
   153:    """
>> 154:    x = some_calculation()
   155:    y = something_else()
   156:    x.baz(y)
   157:    return x.quux()

Existe uma maneira fácil de fazer isso?

    
por a paid nerd 24.02.2011 / 19:13

5 respostas

7

Muitas vezes quando estou procurando algo no grep, eu ligo a opção de contexto (-C). Então, se você quer um contexto baseado na busca por uma palavra-chave, você pode fazer assim:

grep -C3 searchpattern file

Isso lhe dará 3 linhas acima e 3 abaixo do contexto. Aumentar / diminuir conforme necessário. Você também pode ir para quantidades específicas acima e abaixo com um número -A (acima) e um número -B (abaixo). Se você quiser fazê-lo especificamente pelo número da linha, você pode tentar o comando nl para numerar as linhas e, em seguida, grep -C3 com base na correspondência do número. Por exemplo, para obter a linha 26:

nl -n ln -ba inputfile | grep -C3 "^26 "

É um pouco complicado, porque você tem que passar essas opções de formatação para nl para conseguir que ele não coloque abas e outras coisas no formato de numeração. grep também tem uma opção de numeração de linhas (-n) e você poderia passar coisas através do grep duas vezes como este baseado na correspondência de nada primeiro (as aspas duplas) e depois o número da linha em segundo:

grep -n "" inputfile | grep -C3 "^26:"

Apenas certifique-se de usar algum contexto em seu regex para corresponder ao número da linha, para que você também não corresponda a coisas como 126 ou 260, etc.

    
por 24.02.2011 / 19:39
4

Tente isso

head -157 <filename> | tail -7

Uma pequena aritmética é necessária, mas basicamente a ideia é:

head -<line number + trailing lines> | tail -<total lines to see>
    
por 24.02.2011 / 19:22
2

gawk:

awk -v L=154 'NR==L { printf ">> %5s: ", NR; print $0 ; next } (L-3 <= NR) && (NR <= L+3) { printf "   %5s: ", NR; print $0 }' stuff.py

Basta colocá-lo em um script de shell.

    
por 24.02.2011 / 19:20
1

Sim, existem várias maneiras de fazer isso. No bash:

line=154 ; offset=4 ; ((start=line-offset)) ; ((end=line+offset)) ; cat -n stuff.py | sed -n "$start,$end p"

Você pode colocar tudo isso em uma função ou script.

    
por 24.02.2011 / 19:23
0

Isso usa nl para adicionar números de linha configuráveis
Args 1 e 2 são como por sua pergunta (mas não -l )
Args 3 e 4 são o número de linhas de lead e trail (padrão = 3)

[[ "$1" == "" ]] && lnum=0 || lnum=$(($1)); ((lnum==0)) && echo "ERROR: Line number: $1" &&  exit 1 
[[ ! -f "$2"  ]] && echo "ERROR: Input file: $2" && exit 2 || file="$2"
[[ "$3" == "" ]] && lead=3 || ((lead=$3)) # default 
[[ "$4" == "" ]] && tail=3 || ((tail=$4)) # default
((lnum<=lead)) && ((lead=lnum-1))
mesg="/tmp/$USER.$(basename $0).mesg"; [[ -f "$mesg" ]] && rm "$mesg"
marg=": "
mark=">>"
nl -s "$marg" "$file" \
| sed -n "$((lnum-lead)),$((lnum+tail)) p" | tee >(wc -l >"$mesg") \
| sed "s/^\([ ]*$lnum\)$marg\(.*\)/$mark/"
lnct=$(cat "$mesg"); rm "$mesg"
((lnct<((lead+tail+1)))) && echo "Waring: EOF"

Saída

  21: 
  22: class InsertTimestampPlugin(gedit.Plugin):
  23:   def __init__(self):
  24>>    gedit.Plugin.__init__(self)
  25: 
  26:   def insert_datetime(self, action, window):
  27:     doc  = window.get_active_document()
    
por 25.02.2011 / 14:56