d转义控制符

原文

如何格式化串,来显示打印\n\t等?

r"ab\n"
//或
`ab\n`
//或
"abc\\ndef\\tghi"

但如果是运行时串,可能必须用std.regex.replaceAll等来手动转义字符.或用管道手动替换:

string myString = ...;
    string escapedStr = myString
        .chunks(1)
        .map!(c => (c == "\n") ? "\\n" :
               (c == "\r") ? "\\r" :
               (c == "\t") ? "\\t" :
               c)
        .joiner
        .array;

这样:

string a = r"ab\n";
writeln(escape(a)); // => ab\n
//我这样
string escapedStr = myString
  .replace("\n",`\n`)
  .replace("\r",`\r`)
  .replace("\t",`\t`);

或这样:

auto escapedStr = appender!string;
for(c;myString) {
  switch(c) {
  case '\n':
   escapedStr.put("\\n");
  case '\r':
   escapedStr.put("\\r");
  ...
  default:
   escapedStr.put(c);
  }
}

最简单的是这样:

import std.conv;
string str = `Hello "World"
line 2`;
writeln([str].text[2..$-2]); // Hello \"World\"\nline 2

这利用了std.format转义了串数组中字符.我们创建str唯一元素的数组,并转换它为文本.如果没有[2..$-2]切片,输出将是["Hello\"World\"\nline2"].
一个稍微更有效的实现是:

string escape(string s)
{
    import std.array : appender;
    import std.format : FormatSpec, formatValue;

    FormatSpec!char f;
    auto w = appender!string;
    w.reserve(s.length);
    formatValue(w, [s], f);
    return w[][2 .. $ - 2];
}
//反函数

string unescape(string s)
{
import std.format : FormatSpec, unformatValue;

FormatSpec!char f;
string str = `["` ~ s ~ `"]`;
return unformatValue!(string[])(str, f)[0];
}

escape()unescape()应为std.format部分,然后,可直接用std.format.internal.write.formatElement来避免转换至数组.

没有分配.如下需要1符缓冲区来避免发送包围的引号.

struct EscapedString
{
   string[1] str;
   this(string str) @nogc pure nothrow @safe { this.str[0] = str; }
   void toString(Out)(auto ref Out output)
   {
      import std.format;
      import std.range;
      char buf; // 0xff => 空的, 0x0, 空的,但不是第1个
      void putter(const(char)[] data) {
         if(!data.length) return;
         if(buf != 0xff)
         {
            if(buf)
               put(output, buf);
         }
         else
            // 跳过第1个 "
            data = data[1 .. $];
         if(!data.length){
            buf = 0;
            return;
         }
         put(output, data[0 .. $-1]);
         buf = data[$-1];
      }
      scope x = &putter;
      formattedWrite(x, "%(%s%)", str[]);
   }
}

格式中公开转义功能会很好,就不需要这种技巧了.
自定义包装串.

struct String {
  string str;
  alias str this;
  import std.format, std.string;
  void toString(scope void delegate(const(char)[]) sink,FormatSpec!char fmt)const
  {
    auto arr = str.lineSplitter;
    if(fmt.spec == 'n') {
      sink.formattedWrite("%-(%s\\n%)", arr);
    } else sink.formattedWrite("%s", str);
  }
} unittest {
  import std.stdio;
  auto str = `这是
串`;
  String Str; // 简单构造器
  Str = str; // 直接赋值

  Str.writefln!"%n"; // "这是\n串"
  Str.writefln!"%s"; /*
这是
串
*/
}
posted @   zjh6  阅读(20)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示