加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

使用Unix工具处理文本:搜索并替换不在某些行之间的所有文本

发布时间:2020-12-15 22:17:30 所属栏目:安全 来源:网络整理
导读:我想在一堆* .org文件上做一些文本处理.我想在每个文件中更改以下内容: [my description](link) 至 [[link][my description]] , `some text` 至 =some text= , ## some heading 至 ** some heading , *some italics* 至 /some italics/ ,和 **some bold**
我想在一堆* .org文件上做一些文本处理.我想在每个文件中更改以下内容:

[my description](link)

[[link][my description]]

,

`some text`

=some text=

,

## some heading

** some heading

,

*some italics*

/some italics/

,和

**some bold**

*some bold*

.是的,这是org-mode语法的IS markdown语法.我知道pandoc.需要注意的是我想要进行上述更改,除非它们出现在以下块中:

#+BEGIN_EXAMPLE
don't want above changes to take place in this block
...
#+END_EXAMPLE

因此,我不能使用pandoc.我想根据上述要求使用某种unix脚本处理这些文件:awk,sed,python,perl,bash等.一旦我有了一个工作脚本,我就可以修改它并从中学习.

谢谢你的帮助!

解决方法

Perl解决方案

这是我为@ jkerian脚本建议的简化更改的结果:使用触发器操作符和-p.我还修复了他的正则表达式,在RHS中使用正确的$1和$2,从s ///到s :::改变分隔符以避免LTS(“Leaning Toothpick Syndrome”),并添加/ x以提高可读性.在处理粗体和斜体时存在逻辑错误,我已经修复了.我添加了注释,显示每种情况下的转换应该与原始问题描述相对应,并对齐转换的RHS以使它们更易于阅读.

#!/usr/bin/perl -p
#
# the -p option makes this a pass-through filter
#####################################################

# omit protected region
next if /^#+BEGIN_EXAMPLE/ .. /^#+END_EXAMPLE/;

# `some text`                      ?   =some text=
s: ` ( [^`]* ) `                       :=$1=:gx;

# [desc](link)                     ?   [[link][desc]]
s: [ ( [^]]* ) ] ( ( [^)]* ) )     :[[$2][$1]]:gx;

# ^## some heading ? ** some heading
#      NB: can't use /x here or would have to use ugly #
s:^##:**:;   

# *some italics*                   ?   /some italics/
s: (?!< * ) * ( [^*]+ ) * (?! *)   :/$1/:gx;

# **some bold**                    ?   *some bold*
s: *{2} ( [^*]+ ) *{2}               :*$1*:gx;

看看这有多容易? Perl中只有6行简单易读的代码.在Perl中很容易,因为Perl专门用于编写这种过滤器非常简单,而Python则不然. Python有独立的设计目标.

虽然你当然可以在Python中重写它,但是不值得这么麻烦,因为Python根本就不是为这类东西而设计的. Python缺少-p“make-me-a-filter”标志,用于隐式循环和隐式打印. Python缺少隐式累加器变量. Python缺少内置的正则表达式. Python缺少s ///运算符. Python缺少有状态的翻转操作符.所有这些都有助于使Perl解决方案比Python解决方案更容易阅读,编写和维护.

但是,你不应该认为这总是存在的.它没有.在其他领域,您可以提出Python在这些方面领先的问题.但不是在这里.这是因为这个过滤器是Perl专注的专业领域,而不是Python.

因此,与简单的Perl版本相比,Python解决方案将更长,更嘈杂,更难以阅读 – 因此更难维护 – 因为Perl旨在简化操作,这是其目标应用领域之一.尝试用Python重写它,并注意它是多么令人讨厌.当然有可能,但不值得麻烦,或维护噩梦.

Python版本

#!/usr/bin/env python3.2

from __future__ import print_function

import sys
import re

if (sys.version_info[0] == 2):
    sys.stderr.write("%s: legacy Python detected! Please upgrade to v3+n"
                   % sys.argv[0] )
    ##sys.exit(2)

if len(sys.argv) == 1:
    sys.argv.append("/dev/stdin")

flip_rx = re.compile(r'^#+BEGIN_EXAMPLE')
flop_rx = re.compile(r'^#+END_EXAMPLE')

#EG# `some text`  -->   =some text=
lhs_backticks = re.compile(r'` ( [^`]* ) `',re.VERBOSE)
rhs_backticks =            r'=1='

#EG# [desc](link)  -->  [[link][desc]]
lhs_desclink  = re.compile(r' [ ( [^]]* ) ] ( ( [^)]* ) ) ',re.VERBOSE)
rhs_desclink  =            r'[[2][1]]'

#EG# ^## some heading  -->  ** some heading
lhs_header    = re.compile(r'^##')
rhs_header    =            r'**'

#EG# *some italics*  -->  /some italics/
lhs_italics   = re.compile(r' (?!< * ) * ( [^*]+ ) * (?! *)  ',re.VERBOSE)
rhs_italics   =            r'/1/'

## **some bold**  -->  *some bold*
lhs_bold      = re.compile(r'*{2} ( [^*]+ ) *{2}',re.VERBOSE)
rhs_bold      =            r'*1*'

errcnt = 0

flipflop = "flip"

for filename in sys.argv[1:]:
    try:
        filehandle = open(filename,"r")
    except IOError as oops:
        errcnt = errcnt + 1
        sys.stderr.write("%s: can't open '%s' for reading: %sn"
                      % ( sys.argv[0],filename,oops) )
    else:
        try:
            for line in filehandle:

                new_flipflop = None

                if flipflop == "flip":
                    if flip_rx.search(line):
                        new_flipflop = "flop"
                elif flipflop == "flop":
                    if flop_rx.search(line):
                        new_flipflop = "flip"
                else:
                    raise FlipFlop_SNAFU

                if flipflop != "flop":
                    line = lhs_backticks . sub ( rhs_backticks,line)
                    line = lhs_desclink  . sub ( rhs_desclink,line)
                    line = lhs_header    . sub ( rhs_header,line)
                    line = lhs_italics   . sub ( rhs_italics,line)
                    line = lhs_bold      . sub ( rhs_bold,line)                        
                print(line,end="")

                if new_flipflop != None:
                    flipflop = new_flipflop

        except IOError as oops:
            errcnt = errcnt + 1
            sys.stderr.write("%s: can't read '%s': %sn"
              % ( sys.argv[0],oops) )
        finally:
            try:
                filehandle.close()
            except IOError as oops:
                errcnt = errcnt + 1
                sys.stderr.write("%s: can't close '%s': %sn"
                  % ( sys.argv[0],oops) )

if errcnt == 0:
    sys.exit(0)
else:
    sys.exit(1)

摘要

使用正确的工具来完成正确的工作非常重要.对于此任务,该工具是Perl,它只占用了7行.只有7件事要做,但不要试着告诉Python.这就像回到具有太多中断堆栈的汇编语言一样.对于这种工作来说,72行的Python显然没有被删除,所有令人痛苦的复杂性和噪音不可读的代码都显示了你究竟为什么.无论语言如何,每行代码的错误率都是相同的,因此如果您在编写N行代码或10 * N行代码之间做出选择,则别无选择.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读