Измените определенную часть файла с помощью сценария оболочки

Каков самый простой способ поиска слова в файле, указанном в командной строке, с этим форматом

./<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 

Я думаю, что это выполнимо с perl или sed, но поскольку я новичок, у меня есть только некоторые awk-знания. Если вы сможете уточнить свой ответ, это будет оценено по достоинству.

  • Сценарий оболочки для записи выбранных полей в одну строку
  • tar-каталоги, содержащие пробелы
  • Создание пустого файла с именем переменной в скрипте
  • Автоматический запуск определенных скриптов при первом входе в систему / при запуске ПК
  • Рекурсивно удалять файлы с idx> 10000
  • Как проверить число, меньшее другого числа
  • динамическое отображение текущего процесса?
  • скрипт запущен в .xinitrc остается в процессах
  • 4 Solutions collect form web for “Измените определенную часть файла с помощью сценария оболочки”

    Редактирование текстовых файлов без временного файла является плохой идеей и обычно не выполняется в сценариях 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 

    Одна вещь, которую вы, похоже, ищете, – это синтаксический анализ командной строки. Достаточный синтаксический анализ может быть выполнен с помощью case в оболочке POSIX.

    Следующий AWK полностью подходит для выполнения этого преобразования. Для этого вы имеете две альтернативы: используйте GNU awk (с -i ), как предлагает Джон, или используйте временный файл. Ниже приведен пример использования mktemp , хотя mktemp не является POSIX, он почти в любой системе * nix

     #!/bin/sh while test $# -gt 0 do case "$1" in -f) file="$2" shift shift ;; --edit) id="$2" column="$3" value="$4" shift shift shift shift ;; *) echo "Usage:" echo " $0 -f <file> --edit <id> <column> <value>" exit ;; esac done # debug echo "edit [$file] in [$id] change column [$column] to [$value]" tmpf=`mktemp` awk -v FS="|" -v OFS="|" "/^$id/ { \$$column = \"$value\" }1" "$file" > "$tmpf" mv "$tmpf" "$file" 

    Идея состоит в том, чтобы избежать правильных символов при передаче программы awk. Предполагая, что сценарий выше называется script.sh вы можете просто сделать:

     ./script.sh -f myfile --edit 1001 3 "It's a me Mario" 

    У этого все еще есть некоторые проблемы, которые я адресую ниже, чтобы не сгруппировать его. Сначала вы также должны проверить наличие пустого числа аргументов:

     if test $# -eq 0 then echo Usage exit fi 

    А во-вторых, использование простого mv иногда опасно. В частности, когда что-то пойдет не так, и скрипт не производит никакого вывода. Всегда полезно добавить что-то подобное вокруг mv , которое перезапишет вход:

     if test -s "$tmpf" then mv "$tmpf" "$file" else echo Something went wrong fi 

    Предположим, что у вас есть файл, как показано ниже, и вам нужно получить вывод, как указано:

    Входной файл:

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

    Выход должен быть:

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

    Попробуйте это:

     grep -rn "1001" file1 | awk -F '|' '{export $2=<new value>;print $2}' \; 
    1. В основном grep -rn "1001" file1 даст строку:

      1001|text4|text5|text6

    2. После того, как вы получите вышеупомянутый вывод, используйте awk для изменения значения второго столбца (который разделен по полю « | ») и распечатайте значение.

    У меня нет среды для ее выполнения в настоящий момент, но я уверен, что логика будет полезна для того, чего вы хотите достичь.

    Вывод: я бы предложил не использовать временные файлы в сценариях, потому что, если мы будем использовать больше этих временных назначений файлов, производительность сервера будет ухудшаться, потому что на сервере произойдет большее количество операций ввода-вывода, что в свою очередь ухудшит его производительность и сделает сервер медленный.

    Оболочка оболочки оболочки с одним слоем вокруг некоторого простого кода sed :

     # Usage: foo <file2> <id> <column> <value> foo() { sed -i "/^$2|/s/[^|]*/$4/$3" "$1" ; } 

    Пример:

      foo file2 1001 2 Marios ; cat file2 

    Вывод:

     1000|text1|text2|text3 1001|Marios|text5|text6 1002|text7|text8|text9 
    Linux и Unix - лучшая ОС в мире.