2012-04-13 4 views
3

Parsen Ich habe eine meiner großen Datei alsN-ten Zeile in der Datei erhalten, nachdem eine andere Datei

foo:43:sdfasd:daasf
bar:51:werrwr:asdfa
qux:34:werdfs:asdfa
foo:234:dfasdf:dasf
qux:345:dsfasd:erwe
...............

hier 1. Spalte foo, bar und qux usw. sind Dateinamen. und die zweite Spalte 43, 51, 34 usw. sind Zeilennummern. Ich möchte die N-te Zeile (angegeben in der 2. Spalte) für jede Datei (in der 1. Spalte angegeben) drucken. Wie kann ich oben in Unix-Shell automatisieren. Eigentlich oben genannte Datei wird beim Kompilieren erzeugt und ich möchte eine Warnzeile im Code ausgeben.

-Danke,

Antwort

0
awk 'NR==4 {print}' yourfilename 

or 

cat yourfilename | awk 'NR==4 {print}' 

Das oben wird man für die 4. Zeile in Ihrer file.You arbeiten kann die Zahl nach Ihren Anforderungen ändern.

+0

die Zeilennummer weitergeben müssen: 'awk -vn = $ lineno 'NR == n {print; exit}' file' –

+0

Wenn Die Datei wird mitten in einer anderen verarbeitet, dann sollten wir die Option -v verwenden. Aber wenn es ein expliziter Prozess ist, dann brauchen wir die Option -v nicht. – Teja

2
while IFS=: read name line rest 
do 
    head -n $line $name | tail -1 
done < input.txt 
+0

Wenn Sie nur die betreffende Zeile wollen: 'head -n $ line $ name | tail -1' –

+0

@glennjackman Danke – kev

2

while IFS=: read file line message; do 
    echo "$file:$line - $message:" 
    sed -n "${line}p" "$file" 
done <yourfilehere 
+1

für die Effizienz: 'sed -n" $ {line} {p; q} "' –

+0

Es ist eine gute Übung, IFS zu speichern, bevor es geändert wird, und es in den ursprünglichen Zustand wiederherzustellen, nachdem es nicht ist länger benötigt. Wie: OFS = $ IFS; ...; IFS = $ OFS' – vyegorov

+0

vyegorov: das obige ändert nur für die Dauer des Lesebefehls. Sogar innerhalb des Körpers der Schleife ist es auf seinen Standardwert zurückgesetzt. –

0
sed -nr '3{s/^([^:]*):([^:]*):.*$/\1 \2/;p}' namesNnumbers.txt 
qux 34 
  • -n keine Ausgabe standardmäßig
  • -r reguläre Ausdrücke (vereinfacht die Pars mit)
  • in Zeile 3 do {... ; p} (Druck am Ende)
  • s ubstitute foobarbaz mit foo bar

So mit den Werten zu arbeiten:

fnUln=$(sed -nr '3{s/^([^:]*):([^:]*):.*$/\1 \2/;p}' namesNnumbers.txt) 

fn=$(echo ${fnUln/ */}) 
ln=$(echo ${fnUln/* /}) 
sed -n "${ln}p" "$fn" 
+0

Die Frage ist, wie man Zeile 34 aus der Datei "qux" (und ähnlich für alle anderen Zeilen) –

+0

@ glennjackman: Ich weiß. Mit "qux" und "34" ist es trivial: 'sed -n" $ {lineno} p "" $ filename "'. Denkst du, ich sollte das in meine Antwort aufnehmen? –

0

Gerade in awk, aber wahrscheinlich schlechtere Leistung als Antworten von @kev oder @MarkReed. Allerdings verarbeitet es jede Datei nur einmal. Benötigt awk GNU

gawk -F: ' 
    BEGIN {OFS=FS} 
    { 
     files[$1] = 1 
     lines[$1] = lines[$1] " " $2 
     msgs[$1, $2] = $3 
    } 
    END { 
     for (file in files) { 
      split(lines[file], l, " ") 
      n = asort(l) 
      count = 0 
      for (i=1; i<=n; i++) { 
       while (++count <= l[i]) 
        getline line < file 
       print file, l[i], msgs[file, l[i]] 
       print line 
      } 
      close(file) 
     } 
    } 
' 
0

Dies könnte für Sie arbeiten:

sed 's/^\([^,]*\),\([^,]*\).*/sed -n "\2p" \1/' file | 
sort -k4,4 | 
sed ':a;$!N;s/^\(.*\)\(".*\)\n.*"\(.*\)\2/\1;\3\2/;ta;P;D' | 
sh