Javascript Regexp可在文件中查找具有特定结构的多个空格

时间:2018-08-24 13:49:18

标签: javascript regex

我正在寻找可满足以下要求的Javascript正则表达式引擎中使用的正则表达式。

我有一个文件,其内容结构如下(框内的文本):

       Column 1        Column 2     Column 3
       _______________________________________________________________________________________________
line  1|Heading 1     Heading 2     Heading 3                                                        |
line  2|      123           456     Quisque imperdiet nibh nec fermentum sollicitudin.               |
line  3|                            Vestibulum eu   elit rutrum, eleifend ligula eu, interdum massa. |
line  4|      789           012     Suspendisse vel   urna vulputate, porta ex ut, varius felis.     |
line  5|                            Praesent a metus faucibus, porttitor magna at, fermentum libero. |
line  6|                                                                                             |
line  7|                                                                                             |
line  8|Heading 1     Heading 2     Heading 3                                                        |
line  9|      123           456     Quisque imperdiet nibh nec fermentum sollicitudin.               |
line 10|                            Vestibulum eu   elit rutrum, eleifend ligula eu, interdum massa. |
line 11|      789           012     Suspendisse vel   urna vulputate, porta ex ut, varius felis.     |
line 12|                            Praesent a metus faucibus, porttitor magna at, fermentum libero. |
       |_____________________________________________________________________________________________|

请注意,该文件不包含制表符,仅包含空格,但是我希望将正则表达式扩展为能够处理制表符。

列说明:

  • 标题行只是字母。我已经知道如何创建正则表达式来匹配标题行。

  • 前两列只能为空,或者只能包含任意位数的数字。

  • 第三列也可以包含字母,数字和一些特殊字符的任意组合(任何类型的括号-弯曲,圆角,斜线,斜线,句号,连字符,等号)

    • 第三列可能包含一个数字,后跟一个空格,后跟一个单词或特殊字符(这些示例是第三列中的有效条目5 RANDOMWORD5 (10),{{1 }})

    • 第三列将永远不会包含:(1)一个数字,(2)仅用空格分隔的数字

我想要一个正则表达式,该表达式将允许我在第三列的内容中匹配多余的空格(两个或多个空格,制表符或制表符或空格的任意组合),以便我可以轻松地删除它们。目标是在第三列中找到多个空格,并用一个空格替换。

我想完全忽略标题行。

我也不想匹配前两列中出现的数字周围的空格。请注意,前两列可能并不总是包含数字。

到目前为止,我能够拼凑的正则表达式如下:

5 AND 10

  • /(?=^(?:(?!Heading 1 Heading 2 Heading 3).)*$)([ \t]*[\S]+[^\n]*)[ \t]{2,}/允许我完全忽略标题行。

  • /(?=^(?:(?!Heading 1 Heading 2 Heading 3).)*$)/允许我在前两列中没有数字的行中找到多个空格。但是,这个问题是,它会与第二列中的数字后面的空格匹配(例如第2行和第9行),我不想这样做。

如果Javascript支持落后,我认为这个问题很容易解决,否则我对如何解决这个问题感到困惑。

编辑1:抱歉,我最初的问题不清楚。我不是在寻找Javascript代码,而只是在Javascript正则表达式引擎中工作的正则表达式。

此外,相对于分多个步骤,我更喜欢单个regexp表达式。

编辑2:在规范中添加了更多详细信息。

编辑3:Lookbehind断言已被JavaScript标准接受,并且在编写此注释时,部分但不是全部JavaScript引擎都支持。请参阅:Javascript: negative lookbehind equivalent?。使用lookbehinds的单个正则表达式可能会实现此目的,但我尚未对此进行测试。

非常感谢您的帮助。

3 个答案:

答案 0 :(得分:1)

在这种情况下,正则表达式将不起作用,因为前两列可能会被省略,并且前两列的字符集是第三列字符集的子集。因此,如果不知道列的宽度,就无法区分第三列的开头。

我认为解决此问题的唯一方法是检查带有标题的行,以查明每列的宽度,然后使用该行查找第三列的开头。它应该非常简单,您应该可以使用某种子字符串功能来做到这一点。

答案 1 :(得分:1)

我找不到只使用一次替换的解决方案。我认为您需要对该字符串进行多次迭代。

我相信这会起作用(userID Name function1Enabled function2Enabled function3Enabled 1 aaa True True False 2 bbb False True True 3 ccc True False True ),但我不确定:

set-cookie

旁注

  • /** * /test/integration/controllers/entrance/login.test.js */ 'use strict'; const supertest = require('supertest'); // also tried describe('Entrance controllers', () => { describe('/api/v1/entrance/login', () => { before(() => { this._url = '/api/v1/entrance/login'; return supertest(sails.hooks.http.app).get('/login') .then(getRes => { const reTokenCapture = /_csrf:\s*unescape\('([^']+)'\)/; const foundToken = reTokenCapture.exec(getRes.text); this._csrf = sails.config.security.csrf ? foundToken[1] : ''; this._cookie = getRes.headers['set-cookie'].join('; '); }); }); it('should accept the session ID & CSRF token procured by GET /login', () => { return supertest(sails.hooks.http.app) .put(this._url) .set('Cookie', this._cookie) .set('X-CSRF-Token', this._csrf) .send({ emailAddress: 'admin@example.com', password: 'abc123', }) .expect(200); }); it('should reject requests without a CSRF token', () => { return supertest(sails.hooks.http.app) .put(this._url) .set('Cookie', this._cookie) .expect(403); }); it('should reject requests without a session cookie', () => { return supertest(sails.hooks.http.app) .put(this._url) .set('Cookie', '') .set('x-csrf-token', this._csrf) .expect(403); }); it('should reject requests with invalid tokens', () => { return supertest(sails.hooks.http.app) .put(this._url) .set('Cookie', 'sails.sid=foo; Path=/; HttpOnly') .set('X-CSRF-Token', 'foo') .send({ emailAddress: 'admin@example.com', password: 'abc123', }) .expect(403); }); it('should reject requests with invalid credentionals', () => { return supertest(sails.hooks.http.app) .put(this._url) .set('Cookie', this._cookie) .set('X-CSRF-Token', this._csrf) .send({ emailAddress: 'user@example.com', password: 'password' }) .expect(401); }); it('should reject get requests', () => { return supertest(sails.hooks.http.app) .get(this._url) .set('Cookie', this._cookie) .set('X-CSRF-Token', this._csrf) .send({ emailAddress: 'admin@example.com', password: 'abc123', }) .expect(404); }); it('should reject post requests', () => { return supertest(sails.hooks.http.app) .post(this._url) .set('Cookie', this._cookie) .set('X-CSRF-Token', this._csrf) .send({ emailAddress: 'admin@example.com', password: 'abc123', }) .expect(404); }); }); }); 是一个任意数字,与我认为此处段落的边距相对应;
  • 此解决方案可能根本不是很快;
  • 这是一个优秀第一个问题!

答案 2 :(得分:1)

(我认为)仅凭JavaScript正则表达式是无法实现的。即使您设法扭曲了某些科学怪人的正则表达式怪物,也很难维护。

提供输入文字

Heading 1     Heading 2     Heading 3                                                       
      123           456     Quisque imperdiet nibh nec fermentum sollicitudin.              
                            Vestibulum eu   elit rutrum, eleifend ligula eu, interdum massa.
      789           012     Suspendisse vel   urna vulputate, porta ex ut, varius felis.    
                            Praesent a metus faucibus, porttitor magna at, fermentum libero.


Heading 1     Heading 2     Heading 3                                                       
      123           456     Quisque imperdiet nibh nec fermentum sollicitudin.              
                            Vestibulum eu   elit rutrum, eleifend ligula eu, interdum massa.
      789           012     Suspendisse vel   urna vulputate, porta ex ut, varius felis.    
                            Praesent a metus faucibus, porttitor magna at, fermentum libero.

一个人可以做

const blocks = text.split(/\n\n/g);
const result = blocks
  .map(block => {
    const [headingRow, ...rows] = block.split('\n');
    const heading3index = headingRow.indexOf('Heading3');
    return rows
      .map(row => {
        const [start, col3] = [row.slice(0, heading3index), row.slice(heading3index)];
        return start + col3.replace(/\s\s+/g, ' ');
      })
      .join('\n');
  })
  .join('\n\n');