这个复杂的查找和替换是否可以作为单行完成?

时间:2016-12-01 16:50:01

标签: python regex awk replace sed

假设我有以下文本:(请注意,这些示例在最初编写后已经简化)

\begin{align} E_{i,j} \left( \Phi_{i-1,j-1} + \Phi_{i-1,j} + \Phi_{i-1,j+1} + \Phi_{i,j-1} + \Phi_{i,j} + \Phi_{i,j+1} + \Phi_{i+1,j-1} + \Phi_{i+1,j} + \Phi_{i+1,j+1} \right) \end{align}

我有两个任务:

  • 将括号中的每个i替换为给定值(例如2)。
  • 将括号中的每个j替换为给定值(例如6)。

约束:

  • 该脚本不应该天真地替换任何 i任何 j,而只能取代_{*,*}模式中的 \begin{align}
  • 大括号之间还有其他构造(例如i+1),不应受到影响。
  • 只要有数学运算符(例如j-2i等),替换就应该是操作的数值结果。 (数学只能是加法或减法。)
  • 应该替换一行中的所有实例 - 而不仅仅是一行中的第一个实例。
  • 我还可以用字母数字模式替换ji(例如N_r - > i。在这种情况下,替换简单明了。
  • 我希望能够用值替换ji或两者
  • 我需要在多行上执行此操作。 (我使用的是文本文件。)

示例输出

示例文字(上图),3 - > \begin{align} E_{3,j} \left( \Phi_{2,j-1} + \Phi_{2,j} + \Phi_{2,j+1} + \Phi_{3,j-1} + \Phi_{3,j} + \Phi_{3,j+1} + \Phi_{4,j-1} + \Phi_{4,j} + \Phi_{4,j+1} \right) \end{align} ,将成为:

j

示例文字(上图),5 - > \begin{align} E_{i,5} \left( \Phi_{i-1,4} + \Phi_{i-1,5} + \Phi_{i-1,6} + \Phi_{i,4} + \Phi_{i,5} + \Phi_{i,6} + \Phi_{i+1,4} + \Phi_{i+1,5} + \Phi_{i+1,6} \right) \end{align} ,将成为:

i

示例文字(上图),3 - > j5 - > \begin{align} E_{3,5} \left( \Phi_{2,4} + \Phi_{2,5} + \Phi_{2,6} + \Phi_{3,4} + \Phi_{3,5} + \Phi_{3,6} + \Phi_{4,4} + \Phi_{4,5} + \Phi_{4,6} \right) \end{align} ,将成为:

i

示例文字(上图),N_r - > \begin{align} E_{N_r,j} \left( \Phi_{N_r-1,j-1} + \Phi_{N_r-1,j} + \Phi_{N_r-1,j+1} + \Phi_{N_r,j-1} + \Phi_{N_r,j} + \Phi_{N_r,j+1} + \Phi_{N_r+1,j-1} + \Phi_{N_r+1,j} + \Phi_{N_r+1,j+1} \right) \end{align} ,将成为:

awk

我的问题:这可以作为一个单行(也许使用awk)完成,如果是这样,怎么做?

如果没有,那么sedpythonsed(或类似)中需要多少行?

我知道python可以很好地处理命令行参数,并且很容易评估数学,但是标记化似乎很难。

我认为我的困难是(1)如何让awk\begin{align} E_{N_r,j} \left( \Phi_{N_r-1,j-1} + \Phi_{N_r-1,j} + \Phi_{N_r-1,j+1} + \Phi_{N_r,j-1} + \Phi_{N_r,j} + \Phi_{N_r,j+1} + \Phi_{N_r+1,j-1} + \Phi_{N_r+1,j} + \Phi_{N_r+1,j+1} \right) \end{align} 获取可变数量的命令行参数(替换;一个或两个),以及(2)如何获取行为在替换是数字(和必须做数学)和符号(并且替换是纯文本)之间进行更改。

Tie-breaker进入可以向后追溯符号字符的版本。例如,如果输入文本如下:

N_r

我希望将i替换为\begin{align} E_{N_r,j} \left( \Phi_{N_r-1,j-1} + \Phi_{N_r-1,j} + \Phi_{N_r-1,j+1} + \Phi_{N_r,j-1} + \Phi_{N_r,j} + \Phi_{N_r,j+1} + \Phi_{N_r+1,j-1} + \Phi_{N_r+1,j} + \Phi_{N_r+1,j+1} \right) \end{align} ,然后结果如下:

i

能够用其他可能包含数学的符号替换符号并正确算数的加分点。例如,它应该用i-1替换_{i-1,j},这样如果找到/[-+]\d+\/[-+]\d+|\{.+?\}|\+\d+|-\d+|\{T\}|X|(0:)*/ ^^^^^^^^^^^^^^^^^ ,它会将其转换为``_ {i-2,j}`。

2 个答案:

答案 0 :(得分:2)

这是你正在寻找的吗?

$ cat tst.awk
{
    while ( match($0,/{[^}]+/) ) {
        tgt = substr($0,RSTART+1,RLENGTH-1)
        if (i != "") { gsub(/i/,i,tgt) }
        if (j != "") { gsub(/j/,j,tgt) }
        split(tgt,halves,/,/)
        for (h in halves) {
            if ( halves[h] ~ /^[0-9]+[+-][0-9]+$/ ) {
                split(halves[h],quarts,/[+-]/)
                halves[h] = quarts[1] + (halves[h]~/+/ ? 1 : -1)*quarts[2]
            }
        }
        printf "%s%s", substr($0,1,RSTART), halves[1] "," halves[2]
        $0 = substr($0,RSTART+RLENGTH)
    }
    print
}

$ awk -v i=3 -f tst.awk file
E_{3,j} \left( \Phi_{2,j-1} + \Phi_{2,j} + \Phi_{2,j+1} + \Phi_{3,j-1} + \Phi_{3,j} + \Phi_{3,j+1} + \Phi_{4,j-1} + \Phi_{4,j} + \Phi_{4,j+1} \right)

$ awk -v j=5 -f tst.awk file
E_{i,5} \left( \Phi_{i-1,4} + \Phi_{i-1,5} + \Phi_{i-1,6} + \Phi_{i,4} + \Phi_{i,5} + \Phi_{i,6} + \Phi_{i+1,4} + \Phi_{i+1,5} + \Phi_{i+1,6} \right)

$ awk -v i=3 -v j=5 -f tst.awk file
E_{3,5} \left( \Phi_{2,4} + \Phi_{2,5} + \Phi_{2,6} + \Phi_{3,4} + \Phi_{3,5} + \Phi_{3,6} + \Phi_{4,4} + \Phi_{4,5} + \Phi_{4,6} \right)

$ awk -v i=N_r -f tst.awk file
E_{N_r,j} \left( \Phi_{N_r-1,j-1} + \Phi_{N_r-1,j} + \Phi_{N_r-1,j+1} + \Phi_{N_r,j-1} + \Phi_{N_r,j} + \Phi_{N_r,j+1} + \Phi_{N_r+1,j-1} + \Phi_{N_r+1,j} + \Phi_{N_r+1,j+1} \right)

根据您的更新要求:

$ cat tst.awk
{
    while ( match($0,/_{[-+ij0-9]+,[-+ij0-9]+/) ) {
        tgt = substr($0,RSTART+2,RLENGTH-2)
        if (i != "") { gsub(/i/,i,tgt) }
        if (j != "") { gsub(/j/,j,tgt) }
        split(tgt,halves,/,/)
        for (h in halves) {
            if ( halves[h] ~ /^[0-9]+[+-][0-9]+$/ ) {
                split(halves[h],quarts,/[+-]/)
                halves[h] = quarts[1] + (halves[h]~/+/ ? 1 : -1)*quarts[2]
            }
        }
        printf "%s%s", substr($0,1,RSTART+1), halves[1] "," halves[2]
        $0 = substr($0,RSTART+RLENGTH)
    }
    print
}

$ awk -v i=3 -v j=5 -f tst.awk file
\begin{align} E_{3,5} \left( \Phi_{2,4} + \Phi_{2,5} + \Phi_{2,6} + \Phi_{3,4} + \Phi_{3,5} + \Phi_{3,6} + \Phi_{4,4} + \Phi_{4,5} + \Phi_{4,6} \right) \end{align}

答案 1 :(得分:1)

您可以创建一个bash函数并使用sed

convert(){
    re='^[0-9]+$'
    if [[ $1 =~ $re ]] && [[ $2 =~ $re ]]; then
        sed -r -e "s/\bi\b/$1/g" -e "s/\bj\b/$2/g" | sed -e "s/$1+1/$(($1+1))/g" -e  "s/$1-1/$(($1-1))/g" -e "s/$2+1/$(($2+1))/g" -e  "s/$2-1/$(($2-1))/g";
    elif [[ $1 =~ $re ]]; then
        sed -r -e "s/\bi\b/$1/g" -e "s/\bj\b/$2/g" | sed -e "s/$1+1/$(($1+1))/g" -e  "s/$1-1/$(($1-1))/g";
    elif [[ $2 =~ $re ]]; then
        sed -r -e "s/\bi\b/$1/g" -e "s/\bj\b/$2/g" | sed -e "s/$2+1/$(($2+1))/g" -e  "s/$2-1/$(($2-1))/g";
    else
        sed -r -e "s/\bi\b/$1/g" -e "s/\bj\b/$2/g";
    fi
}

input文件的位置,

E_{i,j} \left( e^{-1,-1}_{i,j} \Phi_{i-1,j-1} + e^{-1,0}_{i,j} \Phi_{i-1,j} + e^{-1,+1}_{i,j} \Phi_{i-1,j+1} + e^{0,-1}_{i,j} \Phi_{i,j-1} + e^{0,0}_{i,j} \Phi_{i,j} + e^{0,+1}_{i,j} \Phi_{i,j+1} + e^{+1,-1}_{i,j} \Phi_{i+1,j-1} + e^{+1,0}_{i,j} \Phi_{i+1,j} + e^{+1,+1}_{i,j} \Phi_{i+1,j+1}  \right)

<强> TEST1

cat input | convert 3 j

你明白了,

E_{3,j} \left( e^{-1,-1}_{3,j} \Phi_{2,j-1} + e^{-1,0}_{3,j} \Phi_{2,j} + e^{-1,+1}_{3,j} \Phi_{2,j+1} + e^{0,-1}_{3,j} \Phi_{3,j-1} + e^{0,0}_{3,j} \Phi_{3,j} + e^{0,+1}_{3,j} \Phi_{3,j+1} + e^{+1,-1}_{3,j} \Phi_{4,j-1} + e^{+1,0}_{3,j} \Phi_{4,j} + e^{+1,+1}_{3,j} \Phi_{4,j+1}  \right)

测试2

cat input | convert i 5

你明白了,

E_{i,5} \left( e^{-1,-1}_{i,5} \Phi_{i-1,4} + e^{-1,0}_{i,5} \Phi_{i-1,5} + e^{-1,+1}_{i,5} \Phi_{i-1,6} + e^{0,-1}_{i,5} \Phi_{i,4} + e^{0,0}_{i,5} \Phi_{i,5} + e^{0,+1}_{i,5} \Phi_{i,6} + e^{+1,-1}_{i,5} \Phi_{i+1,4} + e^{+1,0}_{i,5} \Phi_{i+1,5} + e^{+1,+1}_{i,5} \Phi_{i+1,6}  \right)

测试3

cat input | convert 3 5

你明白了,

E_{3,5} \left( e^{-1,-1}_{3,5} \Phi_{2,4} + e^{-1,0}_{3,5} \Phi_{2,5} + e^{-1,+1}_{3,5} \Phi_{2,6} + e^{0,-1}_{3,5} \Phi_{3,4} + e^{0,0}_{3,5} \Phi_{3,5} + e^{0,+1}_{3,5} \Phi_{3,6} + e^{+1,-1}_{3,5} \Phi_{4,4} + e^{+1,0}_{3,5} \Phi_{4,5} + e^{+1,+1}_{3,5} \Phi_{4,6}  \right)

测试4

cat input | convert N_r j

你明白了,

E_{N_r,j} \left( e^{-1,-1}_{N_r,j} \Phi_{N_r-1,j-1} + e^{-1,0}_{N_r,j} \Phi_{N_r-1,j} + e^{-1,+1}_{N_r,j} \Phi_{N_r-1,j+1} + e^{0,-1}_{N_r,j} \Phi_{N_r,j-1} + e^{0,0}_{N_r,j} \Phi_{N_r,j} + e^{0,+1}_{N_r,j} \Phi_{N_r,j+1} + e^{+1,-1}_{N_r,j} \Phi_{N_r+1,j-1} + e^{+1,0}_{N_r,j} \Phi_{N_r+1,j} + e^{+1,+1}_{N_r,j} \Phi_{N_r+1,j+1}  \right)