首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >POSIX sh:查找并用函数替换

POSIX sh:查找并用函数替换
EN

Stack Overflow用户
提问于 2018-05-09 10:48:39
回答 1查看 263关注 0票数 0

在JavaScript中,您可以:

代码语言:javascript
复制
someComplexProcessing = (wholeMatch, group1, group2, index, mystr)=> replacement...
mystr.replace(/some.* regex(with) multiple (capture groups)/g, someComplexProcessing)

例如:

代码语言:javascript
复制
const renderTemplate = (str, env)=> str.replace(/{{(.*?)}}/g, (_, name)=> env[name])
renderTemplate('{{salut}} {{name}}!', {salut: 'Hi', name: 'Leo'}) // "Hi Leo!"

最佳的POSIX兼容、通用、变体是什么?

代码语言:javascript
复制
- reusability # eg. a function taking regex, processingFunction, and input, etc - that I could but in my .shellrc/source lib.sh or similar and reuse
- multiline # eg. if "uppercase everything between {{ and }}", `a {{b\nc}}` -> `a B\nC`
- no escape gotchas # eg. it shouldn't break if input, replacement, or regex contains special characters
- POSIX compatible # eg. running it under `docker run --rm -it alpine sh`, etc
- using regex # eg. perl regex seems like the most prominent one, please note differences from it if other is used

meriting:
- no/less dependencies # eg. as portable as possible
- multiple capture groups
- performance
- security # related to no escape gotchas, eg. ok with untrusted input

我已经为bash找到了几个解决方案,以及一些兼容的边缘案例解决方案,但没有一个解决方案与js‘.replace提供的简单性非常接近。最终,我不想过多地考虑实现细节/问题,也不想引入100的MB (主要是到高寒容器,但也使用ubuntu/OSX),从而尝试建立一个可移植的、与posix兼容的片段、函数和模式库。

EN

回答 1

Stack Overflow用户

发布于 2018-05-09 10:48:39

一个无效的、有点转义的输入(假设没有\r) (但不是regex输入转义),解决方案,只有一个捕获组(中间)。尽管是可移植的(只使用trsed (以及printf-z空字符串检查)。(可能有可能将sed部件更改为一般perl regex兼容的部件)

lib.sh:

代码语言:javascript
复制
#!/usr/bin/env sh
multiline_substitute_with_fn () {
  sub_start="$1"; shift; fn_name="$1"; shift; sub_end="$1"; shift; left="$(cat)";
  # uppercase () { cat | tr 'a-z' 'A-Z'; }; echo 'Hello [there]!' | multiline_substitute_with_fn '\[' uppercase '\]'

  # make single-line, sanitize input against _SUB(START|END)_, a\ra {{echo "b\rb"}} c {{echo d}} e
  left="$(echo "$left" | tr '\n' '\r' | sed 's/_SUB/_ASUB/g')"

  while [ ! -z "$left" ]; do
    left="$(echo "$left" | sed "s/$sub_start/_SUBSTART_/")" # a\ra _SUBSTART_echo "b\rb"}} c {{echo d}} e
    printf '%s' "$(echo "$left" | sed 's/_SUBSTART_.*//' | sed 's/_ASUB/_SUB/g' | tr '\r' '\n')" # a\na

    lefttmp="$(echo "$left" | sed 's/.*_SUBSTART_//' | sed "s/$sub_end/_SUBEND_/")" # echo "b\rb"_SUBEND_ c {{echo d}} e
    if [ "$lefttmp" = "$left" ]; then left=''; break; fi
    left="$lefttmp"

    middle="$(echo "$left" | sed 's/_SUBEND_.*//' | tr '\r' '\n')" # echo "b\nb"
    [ ! -z "$middle" ] && printf '%s' "$(echo "$middle" | $fn_name | sed 's/_ASUB/_SUB/g')" # b\nb
    left="$(echo "$left" | sed 's/.*_SUBEND_//')" # c {{echo d}} e
  done
}

使用:

代码语言:javascript
复制
cat file | multiline_substitute_with_fn 'start regex' processingFunction 'end regex'

eg.用法:

代码语言:javascript
复制
#!/usr/bin/env sh
. ./lib.sh # load lib

uppercase () { cat | tr 'a-z' 'A-Z'; };
echo 'Hello [there]!' | multiline_substitute_with_fn '\[' uppercase '\]'
# -> Hello THERE!

eval_template () { # not "safe" in terms of eval
  # echo 'a\na {{echo "b\nb"}} c {{echo d}} e' | eval_template # -> 'a\na b\nb c d e'
  # hello=hi; echo '{{=$hello}} there' | eval_template # -> {{echo "$hello"}} there -> 'hi there'
  fn () {
    middle="$(cat)"
    case "$middle" in =*) middle="echo \"${middle#=}\"" ;; *);; esac # '=$a' -> 'echo "$a"'
    eval "$middle"
  }
  cat | multiline_substitute_with_fn '{{' fn '}}'
}

eval_template <<-EOF
a
a {{echo "b
b"}} c {{echo d}} e
EOF
# -> a
# a b
# b c d e'

echo '{{=$salut}} {{=$name}}!' > my.template
salut=Hi; name="Leo Name";
cat my.template | eval_template
# Hi Leo Name!
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50251555

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档