
Ich entwickle ein Skript, das Berechnungen durchführt, die in eine bereits ausgefüllte Textdatei aufgenommen werden müssen. Das Format der Dateizeilen ist:
1 20/10/16 12:00 take car in the garage joe's garage
Im Skript erhalte ich eine Zahl aus den Berechnungen, und diese Zahl ersetzt die erste Zahl der Zeile. Wenn beispielsweise „calculate“ den Wert 15 zurückgibt, muss das Skript auf die betreffende Datei zugreifen und die betreffende Zeile ändern. Sie sollte folgendermaßen aussehen:
15 20/10/16 12:00 take car in the garage joe's garage
Der Punkt ist, dass ich nicht weiß, wie ich diese Änderung vornehmen soll. Das kann in Bash, Awk, Sed oder jeder anderen verfügbaren Ressource geschehen. Vielen Dank.
Antwort1
Wie wäre es mit:
awk -v old=$oldNum -v new=$newNum \
'{if ($1==old) {$1=new; print} else {print}}' input.txt > output.txt
Habe es so probiert:
$ cat input.txt
2 19/10/16 15:30 some other line
1 20/10/16 12:00 take car in the garage joe's garage
3 17/10/16 5:30 another one
$ oldNum=2
$ newNum=15
Führen Sie den awk-Befehl aus und gehen Sie dann wie folgt vor:
$ cat output.txt
15 19/10/16 15:30 some other line
1 20/10/16 12:00 take car in the garage joe's garage
3 17/10/16 5:30 another one
Ist es das, was Sie wollten? Wenn Sie möchten, dass Ihr Ergebnis in der Originaldatei angezeigt wird, reicht mv
die Ausgabedatei mit dem neuen Namen aus. input.txt
Diese sollte die Eingabedatei überschreiben (verwenden Sie einen Anti-Schrägstrich, \mv
um Aliasing des mv
Befehls zu vermeiden).
HINWEIS: Sie können wahrscheinlich dasselbe Ergebnis mit kürzeren awk-Anweisungen erzielen, diese Syntax macht es jedoch lesbarer. sed
Sie können es wahrscheinlich auf eine noch prägnantere Weise erreichen.
EDIT: Mir ist klar, dass dies funktioniert, wenn Sie nur eine Zahl in Ihrer Datei ändern möchten. Wenn ich Ihr Problem richtig verstehe, möchten Sie die Zahl fürjedenZeile und erstellen Sie eine Datei mit diesen neuen Nummern. Der optimale Weg, dies zu tun, wäre, Ihre Berechnung der neuen Zeilennummer einzuschließeninnendas awk
Skript, auf diese Weise müssen Sie keine Shell-Schleife erstellen, was im Allgemeinen keine gute Idee ist, da das wiederholte Aufrufen von Tools wie awk
, echo
, sed
... sehr kostspielig ist. Sie könnten so etwas tun:
if [ -f $PWD/output.txt ]; then
# Remove old output if present in current directory
\rm -f $PWD/output.txt
fi
awk '{ ###calculation here, result store in newNum###; $1=newNum; print}' input.txt > output.txt
Wenn ich beispielsweise einfach jede Zeilennummer um eins erhöhen möchte:
awk '{$1++; print}' input.txt > output.txt
Wenn Sie Ihre Berechnung nicht darin einschließen können (oder sich nicht trauen) awk
, können Sie eine Schleife über die Datei ausführen, aber das ist, soweit ich bash
Skripting verstehe, ziemlich umständlich:
if [ -f $PWD/output.txt ]; then
# Remove old output if present in current directory
\rm -f $PWD/output.txt
fi
while read line
do
newNum=###Calculation here for current line###
echo $line | awk -v new=$newNum '$1=new' >> output.txt
done <input.txt
Antwort2
Versuche dies..
awk -v num="$variable" '{$1=num}1' input.txt
Antwort3
Hier ist ein kurzes Python-Skript, das genau das tut, was Sie wollen. Die Verwendung ist einfach: Geben Sie ihm die Datei, die Nummer, mit der die Zeile beginnt, und die Nummer, die Sie stattdessen sehen möchten.
Demo:
bash-4.3$ Katze Daten.txt 2 19/10/16 15:30 eine andere Zeile 1 20/10/16 12:00 Auto in die Garage bringen Joes Garage 3 17/10/16 5:30 noch einer bash-4.3$ python renumber.py data.txt 1 15 ['renumber.py', 'data.txt', '1', '15'] bash-4.3$ Katze Daten.txt 2 19/10/16 15:30 eine andere Zeile 15 20/10/16 12:00 Auto in die Garage bringen Joes Garage 3 17/10/16 5:30 noch einer
Code:
import sys
import os
print(sys.argv)
with open(sys.argv[1]) as inputfile:
with open('/tmp/temp.text','w') as tempfile:
for line in inputfile:
old = line.strip().split()
if old[0] == sys.argv[2]:
old[0] = sys.argv[3]
line = ' '.join(old) + '\n'
tempfile.write(line)
os.rename('/tmp/temp.text',sys.argv[1])