Shell-Script

通過 shell 腳本更改文件的特定部分

  • April 13, 2019

使用這種格式在命令行中給出的文件中搜尋單詞的最簡單方法是什麼

./<file1> -f <file2> --edit <id> <column> <value>

我想搜尋一個<id><file2><column><value>.

我試過了

awk -F '|' -v ID="$4" -v Column="$5" \
          -v Value="$6" 'ID==$1 {$Column=Value ;}1' \
          OFS='|' $2>NewFile
mv NewFile $2 ;

但我希望它在沒有臨時文件的情況下完成

例如:

1000|text1|text2|text3
1001|text4|text5|text6
1002|text7|text8|text9

在我執行之後

./<file> -f file2 --edit 1001 2 Marios

它應該有這個變化:

1000|text1|text2|text3
1001|Marios|text5|text6
1002|text7|text8|text9

在沒有臨時文件的情況下編輯文本文件是個壞主意,通常不會在 Unix 腳本中完成。它需要重寫整個文件,或者至少是受編輯影響的後綴部分。如果寫入中斷,則文件已損壞。

當然,我們每天都使用文本編輯器這樣做:我們將文件保存在記憶體中,並在保存時將它們覆蓋在磁碟上。不同之處在於所有體面的編輯器都至少保留一個備份,除非該功能被明確禁用(這是一個額外的文件,您可能無法接受),並且編輯器是互動式的:如果保存因任何原因失敗(磁碟滿,系統崩潰,無論如何)一個人知道它。如果不是崩潰,儘管保存失敗,編輯器仍在執行並且文件在記憶體中。使用者可以執行命令將文件保存到其他位置,或者在程序外部採取一些操作以修復某些情況後再次嘗試保存。

TXR 中的解決方案:從記憶體中的副本覆蓋,沒有備份或恢復策略:

#!/usr/local/bin/txr --lisp

(defvarl myname [*args-full* 2])

;; check for required arguments syntax
(unless (and (= (length *args*) 6)
            (equal [*args* 0] "-f")
            (equal [*args* 2] "--edit"))
 (put-line `usage: @myname -f <file> --edit <col1-key> <col-num> <replace>`)
 (exit 1))

;; do in-memory update and overwrite
(let ((file [*args* 1])
     (key [*args* 3])
     (col (pred (tointz [*args* 4]))) ;; pred, because [f #] is zero based
     (val [*args* 5])
     (ss (make-strlist-output-stream))) ;; in-memory string list stream

 ;; awk into memory
 (awk (:inputs file) ;; input from file
      (:output ss) ;; output stream is in-memory string list
      (:set fs "|") ;; field separator is pipe
      ((equal [f 0] key) (set [f col] val)) ;; do replacement
      (t)) ;; true condition with no action -> default print action

 ;; overwrite original file with string list
 (with-stream (out (open-file file "w"))
   (put-lines (get-list-from-stream ss) out)))

會議:

$ diff -u data.orig data
$ ./inplace 
usage: ./inplace -f <file> --edit <col1-key> <col-num> <replace>
$ ./inplace -f data --edit 1001 2
usage: ./inplace -f <file> --edit <col1-key> <col-num> <replace>
$ ./inplace -f data --edit 1001 2 Marios
$ diff -u data.orig data
--- data.orig   2016-10-16 08:05:03.233736781 -0700
+++ data    2016-10-16 08:15:57.412394022 -0700
@@ -1,3 +1,3 @@
1000|text1|text2|text3
-1001|text4|text5|text6
+1001 Marios text5 text6
1002|text7|text8|text9

引用自:https://unix.stackexchange.com/questions/316664