用命令输出替换字符串,每次都不同

时间:2017-11-18 01:11:12

标签: linux sed

我有很多文件,我想用UUID替换类名。我想出了这个

class RequestRunnable(QRunnable):
    def __init__(self, url, json, dialog):
        QRunnable.__init__(self)
        self.mUrl = url
        self.mJson = json
        self.w = dialog

    def run(self):
        r = requests.post(self.mUrl, json=self.mJson)
        QMetaObject.invokeMethod(self.w, "setData",
                                 Qt.QueuedConnection,
                                 Q_ARG(str, r.text))


class Dialog(QDialog):
    def __init__(self, *args, **kwargs):
        QDialog.__init__(self, *args, **kwargs)
        self.setLayout(QVBoxLayout())
        btn = QPushButton("Submit", self)
        btn.clicked.connect(self.submit)
        self.spinner = QtWaitingSpinner(self)

        self.layout().addWidget(btn)
        self.layout().addWidget(self.spinner)

    def submit(self):
        self.spinner.start()
        runnable = RequestRunnable("https://api.github.com/some/endpoint",
                                   {'some': 'data'},
                                   self)
        QThreadPool.globalInstance().start(runnable)

    @pyqtSlot(str)
    def setData(self, data):
        print(data)
        self.spinner.stop()
        self.adjustSize()

当模式仅在每个文件中出现一次时,它工作正常。但是,如果模式出现不止一次,则每个出现的事件都会被相同的数字替换。

Class1.vb

sed -i -r "s/ Class \w(\w|\d)+/ Class C$(python -c 'import uuid;print(uuid.uuid4().hex)')/"
Public Class Class1
    Public ReadOnly Property P As String = "hello"
End Class

Public Class Class2
    Public ReadOnly Property P As String = "hello"
End Class

我希望这两个类有不同的名字。如何修复脚本?

2 个答案:

答案 0 :(得分:1)

$ awk '{gsub(/Class [[:alnum:]]+/, "Class C" int(9999*rand()))} 1' Class1.vb
Public Class C2377
    Public ReadOnly Property P As String = "hello"
End Class

Public Class C5854
    Public ReadOnly Property P As String = "hello"
End Class

以上每次都会以相同的顺序给出相同的随机数。如果每次运行程序时想要不同的随机数,请使用:

awk -v s=$RANDOM 'BEGIN{srand(s)} {gsub(/Class [[:alnum:]]+/, "Class C" int(9999*rand()))} 1' Class1.vb

如何运作

  • gsub(/Class [[:alnum:]]+/, "Class C" int(9999*rand()))

    这会查找正则表达式Class [[:alnum:]]+的出现次数,并使用字符串Class C和从int(9999*rand())计算的四位随机数的串联替换每个正则表达式1。为每一行生成一个新的随机数。

  • <?php $result = mysqli_query($mysqli, "SELECT category.*, cat.name as parentName FROM category left join category as cat on category.parentId = cat.id ORDER BY id ASC"); // using mysqli_query instead while($res = mysqli_fetch_array($result)) { echo "<tr>"; echo "<td>".$res['id']."</td>"; echo "<td>".$res['name']."</td>"; echo "<td>".$res['description']."</td>"; echo "<td>".$res['parentId']."</td>"; echo "<td>".$res['parentName']."</td>"; echo "<td><a href=\"update.php?id=$res[id]&parentId=$res[parentId]\">Edit</a> | <a href=\"action/delete.php?id=$res[id]\" onClick=\"return confirm('Are you sure you want to delete?')\">Delete</a></td>"; } ?>

    对于打印当前行,这是awk的神秘缩写。

答案 1 :(得分:1)

更多是作为概念证明而不是严肃的替代方案:GNU sed解决方案。

sed -E -e '/Class \w+/{h;s/.*/bash -c "echo C\\$RANDOM"/;e' \
    -e 'G;s/(.*)\n(.*Class )\w+(.*)/\2\1\3/}' infile

导致

Public Class C24276
    Public ReadOnly Property P As String = "hello"
End Class

Public Class C28554
    Public ReadOnly Property P As String = "hello"
End Class

以下是它的工作原理:

/Class \w+/ {                           # If the line matches "Class <name>"
    h                                   # Copy pattern space to hold space
    s/.*/bash -c "echo C\\$RANDOM"/     # Write Bash command into pattern space
    e                                   # Replace pattern space with command output
    G                                   # Append hold space to pattern space
    s/(.*)\n(.*Class )\w+(.*)/\2\1\3/   # Swap class name with random number
}

说明:

  • 这使用GNU扩展:特别是\w字符类和e命令。
  • 使用-e将单行版本拆分为两个命令,因为the e command不能跟任何内容,或者任何内容都被解释为命令。
  • 要运行的命令不能只是echo C$RANDOM,因为e命令使用sh而不是Bash,而sh可能没有$RANDOM (比如在Ubuntu上,sh是破折号)。
  • 因为命令是双引号,$中的$RANDOM必须被转义,并且因为sed在shell看到命令之前进行了第一次传递,所以必须进行转义两次。或者,我可以使用

    s/.*/bash -c '\''echo C$RANDOM'\''/
    

    单引号命令,但这也不是很易读。