【问题标题】:JavaScript equivalent to printf/String.FormatJavaScript 等价于 printf/String.Format
【发布时间】:2010-10-11 06:11:18
【问题描述】:

我正在寻找与 C/PHP printf() 或 C#/Java 程序员类似的良好 JavaScript String.Format()IFormatProvider 用于 .NET)。

我现在的基本要求是数字的千位分隔符格式,但处理大量组合(包括日期)的格式会很好。

我意识到 Microsoft 的 Ajax 库提供了 String.Format() 的一个版本,但我们不想要该框架的全部开销。

【问题讨论】:

标签: javascript printf string.format


【解决方案1】:

我没有在列表中看到pyformat,所以我想我会把它扔进去:

console.log(pyformat( 'The {} {} jumped over the {}'
                , ['brown' ,'fox' ,'foobar']
                ))
console.log(pyformat('The {0} {1} jumped over the {1}'
                , ['brown' ,'fox' ,'foobar']
                ))
console.log(pyformat('The {color} {animal} jumped over the {thing}'
                , [] ,{color: 'brown' ,animal: 'fox' ,thing: 'foobaz'}
                ))

【讨论】:

    【解决方案2】:

    另一个建议是你使用字符串模板:

    const getPathDadosCidades = (id: string) =>  `/clientes/${id}`
    
    const getPathDadosCidades = (id: string, role: string) =>  `/clientes/${id}/roles/${role}`
    

    【讨论】:

    • 谢谢,将它放入 lambda 的想法为我省了很多麻烦!
    【解决方案3】:

    我没有看到String.format 变体:

    String.format = function (string) {
        var args = Array.prototype.slice.call(arguments, 1, arguments.length);
        return string.replace(/{(\d+)}/g, function (match, number) {
            return typeof args[number] != "undefined" ? args[number] : match;
        });
    };
    

    【讨论】:

      【解决方案4】:

      用于 jQuery.ajax() 成功函数。仅传递一个参数并将字符串替换为该对象的属性作为 {propertyName}:

      String.prototype.format = function () {
          var formatted = this;
          for (var prop in arguments[0]) {
              var regexp = new RegExp('\\{' + prop + '\\}', 'gi');
              formatted = formatted.replace(regexp, arguments[0][prop]);
          }
          return formatted;
      };
      

      例子:

      var userInfo = ("Email: {Email} - Phone: {Phone}").format({ Email: "someone@somewhere.com", Phone: "123-123-1234" });
      

      【讨论】:

        【解决方案5】:

        使用 sprintf.js - 可以制作出漂亮的小格式

        String.prototype.format = function(){
            var _args = arguments 
            Array.prototype.unshift.apply(_args,[this])
            return sprintf.apply(undefined,_args)
        }   
        // this gives you:
        "{%1$s}{%2$s}".format("1", "0")
        // {1}{0}
        

        【讨论】:

          【解决方案6】:
          /**
           * Format string by replacing placeholders with value from element with
           * corresponsing index in `replacementArray`.
           * Replaces are made simultaneously, so that replacement values like
           * '{1}' will not mess up the function.
           *
           * Example 1:
           * ('{2} {1} {0}', ['three', 'two' ,'one']) -> 'one two three'
           *
           * Example 2:
           * ('{0}{1}', ['{1}', '{0}']) -> '{1}{0}'
           */
          function stringFormat(formatString, replacementArray) {
              return formatString.replace(
                  /\{(\d+)\}/g, // Matches placeholders, e.g. '{1}'
                  function formatStringReplacer(match, placeholderIndex) {
                      // Convert String to Number
                      placeholderIndex = Number(placeholderIndex);
          
                      // Make sure that index is within replacement array bounds
                      if (placeholderIndex < 0 ||
                          placeholderIndex > replacementArray.length - 1
                      ) {
                          return placeholderIndex;
                      }
          
                      // Replace placeholder with value from replacement array
                      return replacementArray[placeholderIndex];
                  }
              );
          }
          

          【讨论】:

            【解决方案7】:

            jQuery Globalize 项目中还有Globalize.format,这是jQuery UI 的官方全球化服务。当您需要文化感知格式时,它很好。

            【讨论】:

              【解决方案8】:

              我需要一个可以以用户喜欢的方式格式化价格(以美分给出)的函数,而棘手的部分是格式由用户指定——我不希望我的用户理解 printf -like 语法或正则表达式等。 我的解决方案有点类似于 Basic 中使用的解决方案,因此用户只需用 # 个位置标记数字,例如:

              simple_format(1234567,"$ ###,###,###.##")
              "$ 12,345.67"
              simple_format(1234567,"### ### ###,## pln")
              "12 345,67 pln"
              

              我相信这对用户来说很容易理解,也很容易实现:

              function simple_format(integer,format){
                var text = "";
                for(var i=format.length;i--;){
                  if(format[i]=='#'){
                    text = (integer%10) + text;
                    integer=Math.floor(integer/10);
                    if(integer==0){
                      return format.substr(0,i).replace(/#(.*#)?/,"")+text;
                    }
                  }else{
                    text = format[i] + text;
                  }
                }
                return text;
              }
              

              【讨论】:

                【解决方案9】:

                arg函数:

                /**
                 * Qt stil arg()
                 * var scr = "<div id='%1' class='%2'></div>".arg("mydiv").arg("mydivClass");
                 */
                String.prototype.arg = function() {
                    var signIndex = this.indexOf("%");
                    var result = this;
                    if (signIndex > -1 && arguments.length > 0) {
                        var argNumber = this.charAt(signIndex + 1);
                        var _arg = "%"+argNumber;
                        var argCount = this.split(_arg);
                        for (var itemIndex = 0; itemIndex < argCount.length; itemIndex++) {
                            result = result.replace(_arg, arguments[0]);
                        }
                    }
                    return result;
                }
                

                【讨论】:

                  【解决方案10】:

                  String.prototype.format = function(){
                      var final = String(this);
                      for(let i=0; i<arguments.length;i++){
                          final = final.replace(`%s${i+1}`, arguments[i])
                      }
                      return final || ''
                  }
                  
                  console.log(("hello %s2 how %s3 you %s1").format('hi', 'hello', 'how'));
                  <h1 id="text">
                     
                  </h1>

                  【讨论】:

                    【解决方案11】:

                    在 typescript 中创建一个名为 format.ts 的文件并将其导入您需要使用格式的任何内容。

                    // contents of format.ts
                    
                    interface String {
                      format(...args: any[]): string;
                    }
                    
                    if (!String.prototype.format) {
                      String.prototype.format = function() {
                        let a = this;
                        let b: any;
                        // tslint:disable-next-line: forin
                        for (b in arguments) {
                          a = a.replace(/%[a-z]/, arguments[b]);
                        }
                        return a;
                      };
                    }
                    

                    要格式化字符串,请使用以下代码:

                    import './format';
                    
                    console.log('Hello, %s!'.format('World'));
                    

                    示例

                    String.prototype.format = function() {
                      let a = this;
                      let b;
                      for (b in arguments) {
                        a = a.replace(/%[a-z]/, arguments[b]);
                      }
                      return a;
                    };
                    
                    console.log('Hello, %s!'.format('World'));

                    【讨论】:

                      【解决方案12】:

                      如果您只需要使用 %s 说明符格式化字符串

                      function _sprintf(message){
                          const regexp = RegExp('%s','g');
                          let match;
                          let index = 1;
                          while((match = regexp.exec(message)) !== null) {
                              let replacement = arguments[index];
                              if (replacement) {
                                  let messageToArray = message.split('');
                                  messageToArray.splice(match.index, regexp.lastIndex - match.index, replacement);
                                  message = messageToArray.join('');
                                  index++;
                              } else {
                                  break;
                              }
                          }
                      
                          return message;
                      }
                      
                      _sprintf("my name is %s, my age is %s", "bob", 50); // my name is bob, my age is 50
                      

                      【讨论】:

                        【解决方案13】:

                        现在有一个叫locutus的包,它可以将其他语言的功能翻译成Javascript,如php、python、ruby等。

                        const printf = require('locutus/php/strings/printf')
                        printf('Hello world');
                        

                        你可以试试这个游乐场codesandbox

                        【讨论】:

                        • 我发现了一个错误并提供了修复。它现在应该可以正常工作了。谢谢你的提及!
                        【解决方案14】:

                        好的,首先我们将设置一些要使用的变量:

                            const date = new Date();
                            
                            const locale = 'en-us';
                            
                            const wDay   = date.toLocaleString(locale, {weekday: 'short'});
                            const month  = date.toLocaleString(locale, {month: 'long'});
                            const year   = date.toLocaleString(locale, {year: 'numeric'});
                            const minute = date.toLocaleString(locale, {minute: 'numeric'});
                            const [hour, ap] = date.toLocaleString(locale, {hour: 'numeric', hour12:true}).split(' ');
                            
                            let mDay = date.toLocaleString(locale, {day: 'numeric'});
                            
                            switch(mDay % 10)
                            {
                                case 1:  mDay += 'st'; break;
                                case 2:  mDay += 'nd'; break;
                                case 3:  mDay += 'rd'; break;
                                default: mDay += 'th'; break;
                            }
                        

                        现在我们已经掌握了所有这些,我们可以像这样格式化字符串:

                            const formatter = (...a) => `${a[0]}, the ${a[1]} of ${a[2]} ${a[3]} at ${a[4]}:${a[5]} ${a[6]}`;
                            const formatted = formatter(wDay, mDay, month, year, hour, minute, ap);
                        

                        我们甚至可以为“格式化程序”函数使用命名参数:

                            const formatter = (wDay, mDay, month, year, hour, minute, ap) => `${wDay}, the ${mDay} of ${month} ${year} at ${hour}:${minute} ${ap}`;
                            const formatted = formatter(wDay, mDay, month, year, hour, minute, ap);
                        

                        如果你注意到,上面的 JS 模板都是回调的结果。如果上面的整段代码被封装在一个预期返回格式化日期的函数中,那么不难想象如何以相同的方式构造一个任意的“格式化程序”函数,该函数可以从外部传入。

                        tl;如果将模板文字放在回调中并使用 args 作为替换,您可以重复使用模板文字。

                        【讨论】:

                          【解决方案15】:

                          这个适用于 {0}、{1} 和 {}。

                          String.prototype.format = function format()
                          {                                                                                                               
                            var msg = this;
                            for(var i in arguments)
                              msg = msg.replace(/\{\}/,arguments[i]).replace(new RegExp('\\{'+i+'\\}','g'),arguments[i]);
                            return msg;
                          }
                          

                          【讨论】:

                            【解决方案16】:

                            你可以使用这个功能

                                        String.prototype.format = function (args) {
                                        var str = this;
                                        return str.replace(String.prototype.format.regex, function(item) {
                                            var intVal = parseInt(item.substring(1, item.length - 1));
                                            var replace;
                                            if (intVal >= 0) {
                                                replace = args[intVal];
                                            } else if (intVal === -1) {
                                                replace = "{";
                                            } else if (intVal === -2) {
                                                replace = "}";
                                            } else {
                                                replace = "";
                                            }
                                            return replace;
                                        });
                                    };
                                    String.prototype.format.regex = new RegExp("{-?[0-9]+}", "g");
                            
                                    // Sample usage.
                                    var str = "She {1} {0}{2} by the {0}{3}. {-1}^_^{-2}";
                                    str = str.format(["sea", "sells", "shells", "shore"]);
                                    alert(str);
                            

                            【讨论】:

                            • 使用parseInt() 作为@hienbt88 在这里产生了令人惊讶的竞争性,性能......我把这个想法的一个整理版本和一个相同的正则表达式缓存变体都放在了板凳上:jsperf.com/stringformat/6#results - parseInt() 实现出现在顶部或顶部附近(与此 q 的回答者发布的来自 sn-ps 的一堆其他版本的 String.format() 相比)。
                            【解决方案17】:

                            bobjs 可以这样做:

                            var sFormat = "My name is {0} and I am {1} years old."; 
                            var result = bob.string.formatString(sFormat, "Bob", 29); 
                            console.log(result); 
                            //output: 
                            //========== 
                            // My name is Bob and I am 29 years old. 
                            

                            【讨论】:

                              【解决方案18】:
                              String.prototype.repeat = function(n) { 
                                  return new Array(++n).join(this); 
                              };
                              
                              String.prototype.pad = function(requiredLength, paddingStr, paddingType) {    
                                  var n = requiredLength - this.length; 
                              
                                  if (n) {
                                      paddingType = paddingType ? paddingType.toLowerCase() : '';
                                      paddingStr = paddingStr || ' ';
                                      paddingStr = paddingStr.repeat( Math.ceil(n / paddingStr.length) ).substr(0, n);
                              
                                      if (paddingType == 'both') {
                                          n /= 2;
                                          return paddingStr.substr( 0, Math.ceil(n) ) + this + paddingStr.substr( 0, Math.floor(n) );
                                      }   
                              
                                      if (paddingType == 'left') {
                                          return paddingStr + this;
                                      }
                              
                                      return this + paddingStr;
                                  } 
                              
                                  return this; 
                              }; 
                              
                              // синтаксис аналогичен printf
                              // 'Привет, %s!'.format('мир') -> "Привет, мир!"
                              // '%.1s.%.1s. %s'.format('Иван', 'Иванович', 'Иванов') -> "И.И. Иванов"
                              String.prototype.format = function() {
                                  var i = 0, 
                                      params = arguments;
                              
                                  return this.replace(/%(?:%|(?:(|[+-]+)(|0|'.+?)([1-9]\d*)?(?:\.([1-9]\d*))?)?(s|d|f))/g, function(match, sign, padding, width, precision, type) {
                                      if (match == '%%') { 
                                          return '%'; 
                                      }
                              
                                      var v = params[i++];
                              
                                      if (type == 'd') { 
                                          v = Math.round(v); 
                                      }
                                      else if (type == 'f') {
                                          v = v.toFixed(precision ? precision : 6);
                                      }
                              
                                      if (/\+/.test(sign) && v > 0) {
                                          v = '+' + v;
                                      }
                              
                                      v += '';
                              
                                      if (type != 'f' && precision) {
                                          v = v.substr(0, precision);
                                      }
                              
                                      if (width) {
                                          v = v.pad(width, padding == '' ? ' ' : padding[0] == "'" ? padding.substr(1) : padding, /-/.test(sign) ? 'right' : 'left'); 
                                      }
                              
                                      return v;
                                  });
                              };
                              
                              // this.name = 'Вася';
                              // console.log( 'Привет, ${name}!'.template(this) );
                              // "Привет, Вася!"
                              String.prototype.template = function(context) {
                                  return this.replace(/\$\{(.*?)\}/g, function(match, name) {
                                      return context[name];
                                  });
                              };
                              

                              【讨论】:

                                【解决方案19】:

                                我开始将JavaString.format(实际上是新的Formatter().format())移植到javascript。初始版本位于:

                                https://github.com/RobAu/javascript.string.format

                                您可以简单地添加 javscript 并调用 StringFormat.format("%.2f", [2.4]); 等。

                                请注意它还没有完成,但欢迎反馈:)

                                【讨论】:

                                • 那么为什么要添加它作为可能的解决方案呢?
                                • “我现在的基本要求是数字的千位分隔符格式” - 它处理得很好
                                【解决方案20】:

                                这不是sprintf 的完全重复;但是,它相似且更强大:https://github.com/anywhichway/stringformatter

                                使用此库的格式表达式采用嵌入式 Javascript 对象的形式,例如

                                format("I have {number: {currency: "$", precision:2}}.",50.2); 
                                

                                将返回"I have $50.20."

                                【讨论】:

                                  【解决方案21】:
                                  export function stringFormate (str: string, ...args: string[]) {
                                       return args.reduce((acc, curr, i) => acc.replace(new RegExp("\\{" + i + "\\}", 'g'), curr), str);
                                  }
                                  

                                  【讨论】:

                                    【解决方案22】:

                                    不是世界上最推荐的功能,但它确实有效。

                                    如果您需要 sprintf,只需复制并粘贴相同的函数并将 return console.log(sb) 更改为 return sb

                                    printf = function(s, /*args...*/) {
                                        a = arguments;
                                        al = a.length;
                                        
                                        if (al <= 1) return -2;
                                        if (al >= 2 && s.toLowerCase().search(/%[a-z]/) == -1) return -1;
                                    
                                        sb = s;
                                        for (i = 1; i <= al - 1; i++) {
                                            sb = sb.replace(/%[a-z]/, a[i]);
                                        }
                                    
                                        return console.log(sb);
                                    }
                                    
                                    var someString = "Hello %s\nIt's %s:%s %s now.\nThe day is %s\n";
                                    printf(someString, "StackOverflowUser", "5", "48", "PM", "beautiful");

                                    【讨论】:

                                      【解决方案23】:

                                      sprintf() 函数在 JavaScript 中模拟为 Vue 过滤器String.prototype.format() 扩展:

                                      /**
                                       * Returns a formatted string.
                                       *
                                       * @param template
                                       * @param values
                                       * @return string
                                       */
                                      String.format = function (template, ...values) {
                                          let i = -1;
                                      
                                          function callback(exp, p0, p1, p2, p3, p4) {
                                              if (exp === '%%') return '%';
                                              if (values[++i] === undefined) return undefined;
                                      
                                              exp = p2 ? parseInt(p2.substr(1)) : undefined;
                                      
                                              let base = p3 ? parseInt(p3.substr(1)) : undefined;
                                              let val;
                                      
                                              switch (p4) {
                                                  case 's': val = values[i]; break;
                                                  case 'c': val = values[i][0]; break;
                                                  case 'f': val = parseFloat(values[i]).toFixed(exp); break;
                                                  case 'p': val = parseFloat(values[i]).toPrecision(exp); break;
                                                  case 'e': val = parseFloat(values[i]).toExponential(exp); break;
                                                  case 'x': val = parseInt(values[i]).toString(base ? base : 16); break;
                                                  case 'd': val = parseFloat(parseInt(values[i], base ? base : 10).toPrecision(exp)).toFixed(0); break;
                                              }
                                              val = typeof (val) == 'object' ? JSON.stringify(val) : val.toString(base);
                                              let sz = parseInt(p1); /* padding size */
                                              let ch = p1 && p1[0] === '0' ? '0' : ' '; /* isnull? */
                                      
                                              while (val.length < sz) val = p0 !== undefined ? val + ch : ch + val; /* isminus? */
                                      
                                              return val;
                                          }
                                      
                                          let regex = /%(-)?(0?[0-9]+)?([.][0-9]+)?([#][0-9]+)?([scfpexd%])/g;
                                      
                                          return template.replace(regex, callback);
                                      }
                                      
                                      String.prototype.format = function() {
                                          return String.format(this, ...arguments);
                                      }
                                      
                                      const StringFormat = {
                                          install: (Vue, options) => {
                                              Vue.filter('format', function () {
                                                  return String.format(...arguments);
                                              });
                                          },
                                      };
                                      
                                      export default StringFormat;
                                      

                                      原答案:JavaScript equivalent to printf/String.Format

                                      【讨论】:

                                        【解决方案24】:

                                        如果您需要 printf,请使用 printf

                                        看起来 90% 的评论者从未使用过格式比 %d 更复杂的 printf。我想知道它们是如何输出的,例如货币价值?

                                        【讨论】:

                                        • 在字符串外格式化。 (213.3244).toFixed(2)存在于JavaScript中,其他语言有其他方法(C#有Decimal.Truncate(),或者你使用Math.Round()/Math.round())。文化信息也以多种语言呈现。 C# 中的 System.Globalization 是一个示例,JavaScript 中的 (324).toLocaleString()。这个答案也只适用于 Node.js,而不是浏览器。考虑到问题没有指定它的浏览器或节点,这个答案可能被认为对这种情况毫无用处(对其他来到这里的人有帮助)。模板字符串是这里最好的解决方案。
                                        【解决方案25】:

                                        我使用模板文字方法,如下所示:

                                        export const messages = {
                                          foo: (arg1, arg2) => `Hello ${arg1} ${arg2}`,
                                          bar: (arg1) => `Hello ${arg1}`,
                                        }
                                        

                                        来自文件:

                                        console.log(messages.foo('Bar', 'World'))
                                        console.log(messages.bar('Foo'))
                                        

                                        【讨论】:

                                          【解决方案26】:

                                          这是 CoffeeScript 的 https://stackoverflow.com/a/4673436/1258486 的实现。

                                          https://gist.github.com/eces/5669361

                                          if String.prototype.format is undefined
                                            String.prototype.format = () ->
                                              _arguments = arguments
                                              this.replace /{(\d+)}/g, (match, number) ->
                                                if typeof _arguments[number] isnt 'undefined' then _arguments[number] else match
                                          

                                          【讨论】:

                                            猜你喜欢
                                            • 1970-01-01
                                            • 1970-01-01
                                            • 1970-01-01
                                            • 2021-09-23
                                            • 1970-01-01
                                            • 2020-02-25
                                            • 2023-04-11
                                            • 1970-01-01
                                            相关资源
                                            最近更新 更多