Функция удара с сохранением информации

Если я понимаю правильно, возможно, что-то как:

awk '{getline repl < "second-file"; sub(/regexp/, repl); print}' < first-file

Или если regexp может появиться несколько раз на строку или не на каждой строке:

perl -pe 's/regexp/chomp($r=<STDIN>);$r/ge' first-file < second-file
16
16.04.2014, 03:02
5 ответов

  • Чтобы получить тот же вывод, который вы заметили в вашем вопросе, все, что вам нужно, это:

  • Вам не нужно искажать. Эти две строки сделают все это в любом shell'е, который притворяется чем-то близким к совместимости с POSIX.

  • Но мне это понравилось. И я хотел продемонстрировать основы того, что делает эту работу немного лучше. Поэтому я немного отредактировал это. Пока что я засунул его в [117963]/tmp[117964], но думаю, что оставлю его себе. Это здесь:

    PROMPT SCRIPT:

    Примечание: недавно узнав о [118408]yash[118409], я построил его вчера. По какой-то причине он не печатает первый байт каждого аргумента строкой [118410]%c[118411] - хотя документы были специфичны насчёт расширений для этого формата, и поэтому, возможно, это связано - но он прекрасно работает с [118412]%.1s

    Вот и всё. Там есть две основные вещи. И вот как это выглядит:

    PARSING [117967]$PWD

                +---------------------------+            +--------------------------+
                |Answer question            |            | ????                     |
                |---------------------------|            |--------------------------|
                | eat pizza                 |            | ????                     |
                |                           |+---------->|                          |
                |                           |            |                          |
                |                           |            |                          |
                |                           |            |                          |
                |                           |            |                          |
                |                           |            |                          |
                +---------------------------+            +---------+----------------+
                                                                   |
                       +-------------------------+                 |
                       | PROFIT!                 |                 |
                       |-------------------------|                 |
                       |                         |                 |
                       |                         |-----------------+
                       |                         |
                       |                         |
                       |                         |
                       |                         |
                       +-------------------------+
    
    Каждый раз, когда [118414]$PS1[118415] оценивается, он разбирает и печатает [118416]$PWD[118417] для добавления в подсказку. Но мне не нравится, что весь [118418]$PWD[118419] переполняет мой экран, поэтому мне нужна только первая буква каждой хлебной крошки в текущем пути вниз к текущему каталогу, который я хотел бы видеть в полном объеме. Например:

    Здесь есть несколько шагов:

    mysqldump -u user -p databasename > dump.sql
    

    IFS=/

    scp dump.sql user@remotehost.ip:
    

    нам придется разделить текущий [118493]$PWD[118494] и самый надежный способ сделать это - разделить [118495]$IFS[118496] на [118497]/[118498]. После этого вообще не стоит беспокоиться - все разделения отсюда будут определяться позиционным параметром оболочки [118499]$@[118500] в следующей команде аналогично:

    mysql -u user -p databasename < dump.sql
    

    set -- ${PWD%"${last=${PWD##/*/}}"}

    Так что это немного хитро, но главное, что мы разделяем [118503]$PWD[118504] на символы [118505]/[118506]. Я также использую расширение параметров для присвоения [118507]$last[118508] всему после любого значения, возникающего между крайним левым и крайним правым [118509]/[118510] косой чертой. Таким образом, я знаю, что если я нахожусь только на [118511]/[118512] и у меня есть только один [118513]/[118514], то [118515]$last[118516] все равно будет равен целому [118517]$PWD[118518] и [118519]$1[118520] будет пустым. Это имеет значение. Я также снимаю [118521]$last[118522] с хвостового конца [118523]$PWD[118524], прежде чем присвоить его [118525]$@[118526].enter image description here

    printf "${1+%c/}". "$@"

    Так что здесь - пока [118529]${1+is set}[118530] мы [118531]printf[118532] распечатываем первый [118533]%c[118534]haracter каждого аргумента нашей оболочки - который мы только что установили для каждого каталога в нашем текущем [118535]$PWD[118536] - за вычетом верхнего каталога - разбиваем на [118537]/[118538]. Таким образом, мы, по сути, просто распечатываем первый символ каждой директории в [118539]$PWD[118540], но верхней. Важно, однако, понимать, что это происходит только в том случае, если [118541]$1[118542] вообще будет установлен, что не произойдет в корне [118543]/[118544] или в одном из каталогов, удалённом из [118545]/[118546], например, в [118547]/etc[118548].

    printintf "$last > "

    $last[118552]] - это переменная, которую я только что присвоил нашей верхней директории. Так что теперь это наш верхний каталог. Она печатает, независимо от того, было ли это последнее утверждение или нет. И для хорошей меры нужно немного [118553]>[118554].

    ="INSERT INTO MyTable (ISAM_ID, ENTITY, CUSTOMER_MEDIA,STATUS,IIN,OID,FVC)"
      & " VALUES (" & A2 & ", '" & B2 & "', '" & C2 
      & "', '" & D2 & "','" & E2 & "', '" & F2 & "', '" & G2 & "', '" & H2 & "');"
    

    Но что с этой переменной?

    INSERT INTO MyTable (ISAM_ID, ENTITY, CUSTOMER_MEDIA,STATUS,IIN,OID,FVC)
       VALUES ( 10001, 'ErferrRR01','MP3','LOADED'
       ,'RRGEE', '232133122dfcsdds212121','TGEE');
    
    И еще условие [118436]$PS2[118437]. Ранее я показывал, как это можно сделать, что вы еще можете найти ниже - это, по сути, вопрос сферы применения. Но есть еще кое-что, если только вы не хотите начать делать кучу [118438]printf \b[118439]ackspaces, а затем пытаться сбалансировать их количество символов... ух. Итак, я делаю так:

    enter image description here

    PS1='$(ps1)${PS2c###*[$((PS2c=0))-9]}'

    Опять же, [118557]${параметр##расширение}[118558] спасает день. Однако здесь немного странно - мы на самом деле устанавливаем переменную, в то время как лишаем ее самой себя. Мы используем ее новое значение - устанавливаем середину полосы - в качестве глобуса, с которого мы ее снимаем. Видите? Мы [118559]##*[118560]вырезаем все из головы нашей переменной инкремента до последнего символа, которым может быть что угодно из [118561][$((PS2c=0))-9][118562]. Таким образом, мы гарантированно не выведем значение, но все равно присвоим его. Это довольно круто - я никогда не делал этого раньше. Но POSIX также гарантирует нам, что это самый портативный способ.

    И именно благодаря POSIX-специфическому [117979]${параметру} $((расширению))[117980], мы сохраняем эти определения в текущей оболочке, не требуя, чтобы мы устанавливали их в отдельную подоболочку, независимо от того, где мы их оцениваем. И поэтому он работает в [117981]dash[117982] и [117983]sh[117984] так же хорошо, как и в [117985]bash[117986] и [117987]zsh[117988]. Мы не используем оболочек/терминальных зависимых экранировок и позволяем переменным тестировать себя. Это и делает переносной код [117989] быстрым.

    Остальное довольно просто - просто увеличиваем наш счетчик для каждого раза, когда вычисляется [117991]$PS2[117992], пока [117993]$PS1[117994] не сбросит его еще раз. Like this:

    PS2='$((PS2c=PS2c+1)) > Так что теперь я могу:

    DASH DEMO

    SH DEMO

    Она работает так же в [117997]bash[117998] или [117999]sh[118000]:

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

    14
    27.01.2020, 19:48
    [117643]Это немного I/O-интенсивно, но вам нужно использовать временный файл, чтобы удерживать значение счетчика.

    Если вас беспокоит необходимость в отдельном файле за сессию оболочки (что кажется незначительным беспокойством; будете ли вы на самом деле печатать многострочные команды в двух разных оболочках одновременно? ), вы должны использовать [118098]mktemp[118099] для создания нового файла для каждого использования.

    4
    27.01.2020, 19:48
    [118673] При таком подходе (функция, запущенная в подоболочке) вы не сможете обновить состояние процесса ведущей оболочки, не проходя через искажения. Вместо этого организуйте запуск функции в ведущем процессе.

    Значение переменной

    PROMPT_COMMAND

    преобразуется в команду, которая выполняется перед выводом на печать строки [119074]PS1[119075].

    8
    27.01.2020, 19:48
    [117649]Вы [118100]не можете использовать переменную оболочки таким образом, и вы уже понимаете, почему. Подоболочка наследует переменные точно так же, как процесс наследует свое окружение: любые внесенные изменения применяются [118102]только [118103] к ней и ее дочерним процессам, а не к каким-либо процессам-предкам.
  • Согласно другим ответам, проще всего спрятать эти данные в файл.
  • Etc.[117654].
  • 1
    27.01.2020, 19:48
    [117647]Для справки, вот мое решение, использующее временные файлы, которые уникальны для каждого процесса оболочки, и удаляются как можно быстрее (чтобы избежать беспорядка, как упоминалось в вопросе):

                                
    0
    27.01.2020, 19:48

    Теги

    Похожие вопросы