如何编辑文本文件中当前的前一行?

时间:2015-05-13 08:47:58

标签: bash

所以我需要的确切。 我有一个文件,我逐行循环,当我发现单词"搜索"我需要在前一行返回并更改单词" false"到"真"在那一行内,但只在那一行而不是所有文件。我是bash的新手以及我所拥有的一切。

backupIndex

3 个答案:

答案 0 :(得分:4)

你可以用纯粹的bash做这件事:

# Declare a function process_file doing the stuff
process_file() {
    # Always have the previous line ready, hold off printing
    # until we know if it needs to be changed.
    read prev

    while read line; do
        if [[ $line == *"[search]"* ]]; then
            # substitute false with true in $prev. Use ${prev//false/true} if
            # several occurrences may need to be replaced.
            echo "${prev/false/true}"
        else
            echo "$prev"
        fi

        # remember current line as previous for next turn
        prev="$line"
    done

    # in the end, print the last line (it was saved as $prev) in the last
    # loop iteration.
    echo "$prev"
}

# call function, feed file to it.
process_file < file

但是,有些工具比纯bash更适合这种文件处理,并且常用于shell脚本:awksed。这些工具通过逐行读取 1 来处理文件,并分别为每一行运行一段代码,保留行之间的某些状态(与上面的代码不同),并提供更强大的文本处理功能设施。

为此,我使用awk

awk 'index($0, "[search]") { sub(/false/, "true", prev) } NR != 1 { print prev } { prev = $0 } END { print prev }' filename

那是:

index($0, "[search]") {       # if the currently processed line contains
  sub(/false/, "true", prev)  # "[search]", replace false with true in the
                              # saved previous line. (use gsub if more than
                              # one occurrence may have to be replaced)
}
NR != 1 {                     # then, unless we're processing the first line
                              # and don't have a previous line,
  print prev                  # print the previous line
}
{                             # then, for all lines:
  prev = $0                   # remember it as previous line for the next turn
}
END {                         # and after the last line was processed,       
  print prev                  # print the last line (that we just saved
                              # as prev)
}

您也可以使用sed

sed '/\[search\]/ { x; s/false/true/; x; }; x; ${ p; x; }; 1d' filename

...但正如你所看到的,sed有点神秘。它有自己的优势,但这个问题对他们没有影响。

附录,根据要求:最重要的是要知道sed读取的内容称为模式空间(大多数命令在其上运行)并且侧面有一个保持缓冲区你可以在线之间保存东西。我们将使用保持缓冲区来保存当前的前一行。代码的工作原理如下:

/\[search\]/ {     # if the currently processed line contains [search]
  x                # eXchange pattern space (PS) and hold buffer (HB)
  s/false/true/    # replace false with true in the pattern space
  x                # swap back. This changed false to true in the PS.
                   # Use s/false/true/g for multiple occurrences.
}
x                  # swap pattern space, hold buffer (the previous line
                   # is now in the PS, the current in the HB)
${                 # if we're processing the last line,
  p                # print the PS
  x                # swap again (current line is now in PS)
}
1d                 # If we're processing the first line, the PS now holds
                   # the empty line that was originally in the HB. Don't
                   # print that.

                   # We're dropping off the end here, and since we didn't
                   # disable auto-print, the PS will be printed now.
                   # That is the previous line except if we're processing
                   # the last line (then it's the last line)

好吧,我确实警告过你sed比awk更隐秘。这段代码的一个警告是它希望输入文件有多行。

1 awk的情况下,它的记录不必是行,而是默认的行。

答案 1 :(得分:1)

一种非常简单的方法是一次读取2行,然后检查第二行中的条件并替换上一行。

while read prev_line               # reads every 1st line
do
 read curr_line                    # reads every 2nd line

if [[ $curr_line == *"[search]"* ]]; then
           echo "${prev_line/false/true}"   
           echo "$curr_line
        else
            echo "$prev_line"
            echo "$curr_line"
        fi 
done < "file.txt"

答案 2 :(得分:0)

你这样做的正确版本是:

groupingView: {
    ...
    formatDisplayField: [
        function (displayValue) { //, value, cm, index, grp) {
            return String(displayValue).substring(0, 5);
        }
    ],
    isInTheSameGroup: function (x, y) {
        return String(x).substring(0, 5) === String(y).substring(0, 5);
    }
}