【问题标题】:Replacing a line in a file after grep commandgrep 命令后替换文件中的一行
【发布时间】:2018-10-30 22:21:40
【问题描述】:

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

【问题讨论】:

  • 请在您的post示例中发布代码标签中的输入和输出示例。
  • 我更新了问题
  • @Blacky:你的意思是 0x0 在你的输出中吗?
  • 不,这就是我想要做的,将文件中的 0x1 更改为 0x0,我只设法得到正确的行,但没有设法替换字符串。
  • @Blacky,您应该为所有帖子提供适当的示例 + 尝试通过投票来鼓励人们(如果您认为他们的帖子仅对您有帮助)并尝试选择一个正确的答案来关闭正确穿线。

标签: macos shell sed


【解决方案1】:

您能否尝试关注一下,如果这对您有帮助,请告诉我。

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

【讨论】:

  • 如果我错了就更正,但是这段代码每次找到“const/4 v1, 0x1”时都会改变字符串?
  • 再看问题,“const/4 v1, 0x1”在文件中重复了很多次。我只想更改上面的行“invoke-virtual {v0, v1}, Landroid/view/SurfaceView;->setSecure(Z)V”
  • @Blacky,请检查我的编辑并让我知道吗?但是由于您没有显示太多示例,因此根据您显示的示例,我只编写了此代码,请检查一下。
  • 代码可以运行但仍然不完美,“setSecure”到“0x0”之间的空行消失了,代码从“0x0”行的开头删除了空格。我会自己修复它,但我不太了解代码
  • @Blacky,让我现在也添加解释。
【解决方案2】:

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

【讨论】:

  • 我查看了输出,但它不起作用,似乎什么也没发生。
  • 你是对的。必须更多地寻找 sed。你可以试试这个 awk。
【解决方案3】:

使用您已经工作的命令找出行号,如果它出现在包含 '设置安全'

$ 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

【讨论】:

  • 这就是我得到的:-bash: 意外标记 `do' 附近的语法错误
  • 你用的是什么操作系统?
  • macOS High Sierra 10.13.4
  • 在 10.12.6 上测试过这个,我唯一需要做的改变就是在 sed 的 -i 标志中添加 '.bu'。 (我已经更新了答案。)
【解决方案4】:

这看起来有点难看,但实际上并不是非常复杂。使用 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,那么从 homebrew 安装 GNU sed 会最不痛苦。

【讨论】:

    猜你喜欢
    • 2010-10-20
    • 2010-10-03
    • 2013-09-25
    • 2018-05-02
    • 1970-01-01
    • 2021-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多