Замена строки в файле после команды grep - PullRequest
0 голосов
/ 21 мая 2018

Я пытаюсь заменить 0x1 на 0x0 в файле, мне удалось получить строку, но мне не удалось заменить строку.

Вот код:

grep -B 2 setSecure filePath | head -n 1

Как я могу перейти отсюда, чтобы изменить строку в файле?Я использую OS X, и я хочу изменить строку только в этой строке.

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

sometext
 .line 344
const/4 v1, 0x1

iput v1, p0, Lnagra/nmp/sdk/NMPVideoView;->mCurrentState:I

const/4 v1, 0x1

invoke-virtual {v0, v1}, Landroid/view/SurfaceView;->setSecure(Z)V

    .line 344
const/4 v1, 0x1

iput v1, p0, Lnagra/nmp/sdk/NMPVideoView;->mCurrentState:I
sometext

Вывод:

const/4 v1, 0x1

Обратите внимание, что в файле много строк, начинающихся с "const / 4 v1, 0x1".

Мне нужно изменить только «0x1» над «invoke-virtual {v0, v1}, Landroid / view / SurfaceView; -> setSecure (Z) V»

Ответы [ 4 ]

0 голосов
/ 21 мая 2018

Это будет выглядеть немного некрасиво, но на самом деле не очень сложно.Используя sed:

sed '1h; 1!H; $!d; x; s@\(const/4 v1, \)0x1\([^\n]*\n[^\n]*\n[^\n]*setSecure[^\n]*\n\)@\10x0\2@' filename

(передайте -i для редактирования на месте после тестирования).Это работает, сначала читая весь файл в буфер хранения, а затем сопоставляя несколько строк одновременно:

1h    # If we're processing the first line, write it to the hold buffer
1!H   # if not, append it to the hold buffer
$!d   # If we're not at the end of the file, we're done with this line here.
x     # When we finally get here, we're at the end of the file, and the whole
      # file is in the hold buffer. Swap hold buffer and pattern space, so the
      # whole file is in the pattern space. 

# Then: apply transformation. The regex is somewhat ugly because of all the \ns,
# but all that's really happening here is that we match const/4 v1, 0x1 followed
# by two lines of which the second contains "setSecure", and then replace the
# 0x1 with 0x0.
#
# To understand it, consider that \n[^\n]*\n matches newline followed by non-
# newline characters followed by another newline, which is exactly one line.
# Similarly, \n[^\n]*setSecure[^\n]*\n matches a line 
s@\(const/4 v1, \)0x1\([^\n]*\n[^\n]*\n[^\n]*setSecure[^\n]*\n\)@\10x0\2@

Поскольку вы используете MacOS: MacOS по умолчанию использует BSD sed, который ограничен в количествепути.Я думаю, что в тот день у него были проблемы с \n в его коде, поэтому вам, возможно, придется поменять их местными символами новой строки.Хотя, честно говоря, если вы собираетесь использовать sed под MacOS, было бы менее болезненно просто установить GNU sed из homebrew.

0 голосов
/ 21 мая 2018

Вы не можете использовать grep для этой задачи, grep только печатать и не изменять файл.
Вы можете использовать awk.

awk -v seen='setSecure' -v search='0x1' -v rplt='0x0' -v lign=1 '
  NR<3 {
    a[NR]=$0
    next }
  $0 ~ seen {
    sub( search , rplt , a[lign] ) }
  {
    a[NR]=$0
    print a[lign]
    delete a[lign++] }
  END {
    for( i=lign ; i<=NR ; i++ )
        print a[i] }
' input

С sed

sed '1N;N;/setSecure[^\n]*$/bA;P;D;:A;s/0x1/0x0/;P;D' input

sed '
  1 
    N
# Always keep two lines in the pattern space
    N
# get a third one
# and search for your word
# if find jump to A
  /setSecure[^\n]*$/bA
# not find
# print the first line of the pattern space
    P
# delete it and start a new cycle
    D
  :A
# the word is find
# do the replacement
    s/0x1/0x0/
# print the first line of the pattern space
    P
# delete it and start a new cycle
    D
' input

Если все в порядке, вы можете добавить -i "" для замены файла

0 голосов
/ 21 мая 2018

Используя вашу уже работающую команду, чтобы узнать номер строки, следующая команда sed заменит все вхождения от 0x1 до 0x0 в строках, начинающихся с 'const / 4', если она появляется как минимум за 2 строки перед строкой, содержащей 'setSecure '

$ for LN in $(grep -n -B 2 setSecure filePath | grep 'const/4' | cut -d '-' -f 1 ) ; do sed -i ${LN}s/0x1/0x0/g filePath  ; done

На Mac, следующие работы:

$ for LN in $(grep -n -B 2 setSecure filePath | grep 'const/4' | cut -d '-' -f 1 ) ; do sed -i.bu ${LN}s/0x1/0x0/g filePath  ; done
0 голосов
/ 21 мая 2018

Не могли бы вы попытаться выполнить следующие действия и сообщить мне, поможет ли это вам.

awk '/const\/4 v1, 0x1/{prev=$0;$NF="0x0";val=$0;getline;print;getline;if($0 ~ /invoke-virtual {v0, v1}/){print val ORS $0} else {print prev};prev=val="";next} 1'  Input_file

Если вам нужно сохранить выходные данные в самом файле Input_file, тогда добавьте > temp_file && mv temp_file Input_file к вышеуказанному коду.

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