在grep命令后替换文件中的一行

时间:2018-05-21 09:33:29

标签: macos shell sed

我正在尝试将文件中的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”开头的行。

我只需更改“invoke-virtual {v0,v1},Landroid / view / SurfaceView; - > setSecure(Z)V”上方的“0x1”

4 个答案:

答案 0 :(得分:0)

请您试着跟随并告诉我这是否对您有帮助。

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附加到上面的代码中。

答案 1 :(得分:0)

您不能使用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“”来替换文件

答案 2 :(得分:0)

使用您已经在工作的命令查找行号,以下sed命令将在以'const / 4'开头的行上替换所有出现的0x1到0x0,如果它在包含'的行之前至少出现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

答案 3 :(得分:0)

这看起来有点难看但实际上并不是非常复杂。使用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的问题,所以你可能不得不为它们交换文字换行符。虽然坦率地说,如果你打算在MacOS下使用sed,那么从自制软件安装GNU sed最不痛苦。