PATHがNode.jsの他のもののサブディレクトリかどうかを判断します。 -- javascript フィールド と regex フィールド と node.js フィールド 関連 問題

Determine if a path is subdirectory of another in Node.js












26
vote

問題

日本語

mqtt handler は、親ディレクトリごとにイベントを発行します。イベントリスナーがあります。例えば:

次のMQTTパスがある場合は、サブスクリリストがあります - これらのパスのイベントリスナーがあります -

  • <コード> test
  • <コード> replyer/request
  • <コード> test/replyer/request

および誰かがトピック<コード> test/replyer/request/@issuer で発行され、2つのイベントが発生しているはずです。<コード> test 、<コード>、<コード> 99887665

どんなパスよりも与えられていて、利用可能な有効なイベントのリストがない場合は、パスが別の親の親である場合にのみチェックする必要があります。正規表現でこれを行うことができますか?もしそうなら、それはどのように見えますか?より単純な/より効率的な解決策はありますか?

英語

I am working on a MQTT handler for which I want to emit an event for each parent directory where there is a event listener. For example:

If there are the following MQTT paths available, where there are subscriptors –there are event listeners for these paths–

  • test
  • replyer/request
  • test/replyer/request

And someone publishes on topic test/replyer/request/@issuer, there should be 2 events emmited: test, test/replyer/request.

Given than any path is possible and there is no list of available valid events, we must check only if a path is a parent of another. Can we do this with regex? If so, how would it look like? Is there a simpler/more efficient solution?

</div
        

回答リスト

9
 
vote
vote
ベストアンサー
 

2017年後半回答

<事前> <コード> const isChildOf = (child, parent) => { if (child === parent) return false const parentTokens = parent.split('/').filter(i => i.length) return parentTokens.every((t, i) => child.split('/')[i] === t) }

Node.jsで作業している場合、それをクロスプラットフォームにしたい場合は、 path モジュールと split('/') に含めます。 split(path.sep)


どのように機能するか:

SOは、ディレクトリが別のディレクトリのサブディレクトリの場合に調べたい(<コード> home/etc など)。

仮説<コード> child と 99887668 Pathsの両方を取り、それらを split ::

を使用してそれらをアレイに変換します。 <事前> <コード> const isChildOf = (child, parent) => { if (child === parent) return false const parentTokens = parent.split('/').filter(i => i.length) return parentTokens.every((t, i) => child.split('/')[i] === t) } 0

const isChildOf = (child, parent) => { if (child === parent) return false const parentTokens = parent.split('/').filter(i => i.length) return parentTokens.every((t, i) => child.split('/')[i] === t) } 1 Arrayのすべてのトークンを繰り返し、ES6のを使用して const isChildOf = (child, parent) => { if (child === parent) return false const parentTokens = parent.split('/').filter(i => i.length) return parentTokens.every((t, i) => child.split('/')[i] === t) } 2 配列の相対位置に対して1つずつチェックします。 const isChildOf = (child, parent) => { if (child === parent) return false const parentTokens = parent.split('/').filter(i => i.length) return parentTokens.every((t, i) => child.split('/')[i] === t) } 3

親のすべてが子供のすべてに一致した場合は、それらが正確に同じディレクトリであることを知っています(<コード> home/etc14 を使用して)、私たちは私たちの答えを持っています。

 

Late 2017 Answer

In ES6.

const isChildOf = (child, parent) => {   if (child === parent) return false   const parentTokens = parent.split('/').filter(i => i.length)   return parentTokens.every((t, i) => child.split('/')[i] === t) } 

If you're working in node.js and you want to make it cross-platform, include the path module and replace split('/') with split(path.sep).


How it works:

So, you want to find out if a directory (like home/etc/subdirectory) is a subdirectory of another directory (like home/etc).

It takes both the hypothesised child and parent paths and convert them into arrays using split:

['home', 'etc', 'subdirectory'], ['home', 'etc'] 

It then iterates through all of the tokens in the parent array and checks them one-by-one against their relative position in the child array using ES6's .every().

If everything in parent matches up to everything in child, knowing that we've ruled out they are exactly the same directory (using child !== parent), we will have our answer.

</div
 
 
         
         
64
 
vote

ノード自体を作業を行いなさい。

<事前> <コード> const isChildOf = (child, parent) => { if (child === parent) return false const parentTokens = parent.split('/').filter(i => i.length) return parentTokens.every((t, i) => child.split('/')[i] === t) } 5

正規化も同様に正規化します。

<事前> <コード> home/etc16

ドライブの間でもWindowsで動作します。

<事前> <コード> const isChildOf = (child, parent) => { if (child === parent) return false const parentTokens = parent.split('/').filter(i => i.length) return parentTokens.every((t, i) => child.split('/')[i] === t) } 7
 

Let Node itself do the work.

const path = require('path'); const relative = path.relative(parent, dir); return relative && !relative.startsWith('..') && !path.isAbsolute(relative); 

It does normalisation for you as well.

const path = require('path');  const tests = [   ['/foo', '/foo'],   ['/foo', '/bar'],   ['/foo', '/foobar'],   ['/foo', '/foo/bar'],   ['/foo', '/foo/../bar'],   ['/foo', '/foo/./bar'],   ['/bar/../foo', '/foo/bar'],   ['/foo', './bar'],   ['C:\Foo', 'C:\Foo\Bar'],   ['C:\Foo', 'C:\Bar'],   ['C:\Foo', 'D:\Foo\Bar'], ];  tests.forEach(([parent, dir]) => {     const relative = path.relative(parent, dir);     const isSubdir = relative && !relative.startsWith('..') && !path.isAbsolute(relative);     console.log(`[${parent}, ${dir}] => ${isSubdir} (${relative})`); }); 

Works on Windows across drives too.

[/foo, /foo] => false () [/foo, /bar] => false (..ar) [/foo, /foobar] => false (..foobar) [/foo, /foo/bar] => true (bar) [/foo, /foo/../bar] => false (..ar) [/foo, /foo/./bar] => true (bar) [/bar/../foo, /foo/bar] => true (bar) [/foo, ./bar] => false (..UserskozhevnikovDesktopar) [C:Foo, C:FooBar] => true (Bar) [C:Foo, C:Bar] => false (..Bar) [C:Foo, D:FooBar] => false (D:FooBar) 
</div
 
 
         
         
1
 
vote

失敗を防ぐために必要とされ、ここで起こって物事のカップルがあります:

  • 万一、私たちは、ファイルシステムのパスを解決しようとすると?
  • (私はそう思います) 1つのディレクトリが別のシンボリックリンクで動作するはずが含まれているかどうかのチェック

私はできるだけ解決ファイルシステムパスに試みの可能経路がどのまたはは存在しないかもしれないかもしれないこと溶液を思い付い

  • スプリットOSのパス区切りのパスます。
  • できるだけファイルシステムのものパス成分の多くとして
  • 解決
  • 解決できませんでした
  • 追加の残りの成分
  • 親と子の間の相対パスは、<コード> .. + path.sep で起動しないし、ないない場合は、<コード> .. は、親パスは、子のパスが含まれています。

このすべての作品、を任意の存在しないパスコンポーネントはディレクトリとファイルのみの(なしシンボリックリンク)を使用して作成されることを想定し。たとえば、スクリプトのみホワイトリストのパスに書き込む必要があるとあなたが信頼できない(ユーザ供給)のファイル名を受け入れていると言います。あなたは PHPの mkdir ののようなものを使用してサブディレクトリを作成することができます<コード> $recursive = true この例のと同様のものステップ、ディレクトリ構造を作成している。

(スタックオーバーフローがNode.jsのサポートまで、実行可能ではない)

はここでのコードは、重要な機能であるである、<コード> resolveFileSystemPath() と pathContains()

 <コード> const kWin32 = false;    const fs = require('fs');  const path = kWin32 ? require('path').win32 : require('path');    ////////// functions //////////    // resolves (possibly nonexistent) path in filesystem, assuming that any missing components would be files or directories (not symlinks)  function resolveFileSystemPath(thePath) {   let remainders = [];     for (    let parts = path.normalize(thePath).split(path.sep); // handle any combination of "/" or "" path separators    parts.length > 0;    remainders.unshift(parts.pop())   ) {    try {     thePath =      fs.realpathSync(parts.join('/')) + // fs expects "/" for cross-platform compatibility      (remainders.length ? path.sep + remainders.join(path.sep) : ''); // if all attempts fail, then path remains unchanged       break;    } catch (e) {}   }     return path.normalize(thePath);  }    // returns true if parentPath contains childPath, assuming that any missing components would be files or directories (not symlinks)  function pathContains(parentPath, childPath, resolveFileSystemPaths = true) {   if (resolveFileSystemPaths) {    parentPath = resolveFileSystemPath(parentPath);    childPath = resolveFileSystemPath(childPath);   }     const relativePath = path.relative(parentPath, childPath);     return !relativePath.startsWith('..' + path.sep) && relativePath != '..';  }    ////////// file/directory/symlink creation //////////    console.log('directory contents:');    console.log();    try {   fs.mkdirSync('parent');  } catch (e) {} // suppress error if already exists    fs.writeFileSync('parent/child.txt', 'Hello, world!');    try {   fs.mkdirSync('outside');  } catch (e) {} // suppress error if already exists    try {   fs.symlinkSync(path.relative('parent', 'outside'), 'parent/child-symlink');  } catch (e) {} // suppress error if already exists    fs.readdirSync('.').forEach(file => {   const stat = fs.lstatSync(file);     console.log(    stat.isFile()     ? 'file'     : stat.isDirectory() ? 'dir ' : stat.isSymbolicLink() ? 'link' : '    ',    file   );  });  fs.readdirSync('parent').forEach(file => {   file = 'parent/' + file;     const stat = fs.lstatSync(file);     console.log(    stat.isFile()     ? 'file'     : stat.isDirectory() ? 'dir ' : stat.isSymbolicLink() ? 'link' : '    ',    file   );  });    ////////// tests //////////    console.log();    console.log(   "path.resolve('parent/child.txt'):       ",   path.resolve('parent/child.txt')  );  console.log(   "fs.realpathSync('parent/child.txt'):    ",   fs.realpathSync('parent/child.txt')  );  console.log(   "path.resolve('parent/child-symlink'):   ",   path.resolve('parent/child-symlink')  );  console.log(   "fs.realpathSync('parent/child-symlink'):",   fs.realpathSync('parent/child-symlink')  );    console.log();    console.log(   'parent contains .:                                ',   pathContains('parent', '.', true)  );  console.log(   'parent contains ..:                               ',   pathContains('parent', '..', true)  );  console.log(   'parent contains parent:                           ',   pathContains('parent', 'parent', true)  );  console.log(   'parent contains parent/.:                         ',   pathContains('parent', 'parent/.', true)  );  console.log(   'parent contains parent/..:                        ',   pathContains('parent', 'parent/..', true)  );  console.log(   'parent contains parent/child.txt (unresolved):    ',   pathContains('parent', 'parent/child.txt', false)  );  console.log(   'parent contains parent/child.txt (resolved):      ',   pathContains('parent', 'parent/child.txt', true)  );  console.log(   'parent contains parent/child-symlink (unresolved):',   pathContains('parent', 'parent/child-symlink', false)  );  console.log(   'parent contains parent/child-symlink (resolved):  ',   pathContains('parent', 'parent/child-symlink', true)  );  

出力:

<事前> <コード> directory contents: file .bash_logout file .bashrc file .profile file config.json dir node_modules dir outside dir parent link parent/child-symlink file parent/child.txt path.resolve('parent/child.txt'): /home/runner/parent/child.txt fs.realpathSync('parent/child.txt'): /home/runner/parent/child.txt path.resolve('parent/child-symlink'): /home/runner/parent/child-symlink fs.realpathSync('parent/child-symlink'): /home/runner/outside parent contains .: false parent contains ..: false parent contains parent: true parent contains parent/.: true parent contains parent/..: false parent contains parent/child.txt (unresolved): true parent contains parent/child.txt (resolved): true parent contains parent/child-symlink (unresolved): true parent contains parent/child-symlink (resolved): false

ライブ例: https://repl.it/repls/LawngreenWorriedGreywareする

出力の最後の行が解決ファイルシステムのパスが(その上に未解決の結果とは異なり)正しい結果をもたらすかを示す、重要なものである。

はファイルシステムが読み込み制限/特定のディレクトリへの書き込みは、私がNode.jsのが彼らの組み込みコマンドにこの機能が組み込まれて期待していること、セキュリティのために非常に重要です。 <コード> kWin32 のフラグが動作している場合は私に知らせてくださいので、私は、ネイティブのWindowsボックス上でこれをテストしていません。時間が許す限り、私はこの答えをキュレートしてみましょう。

 

There are a couple of things going on here that are needed to prevent failure:

  • Should we attempt to resolve filesystem paths? (I think so)
  • Checking if one directory contains another should work with symlinks

I came up with a solution that attempts to resolve filesystem paths as much as possible while allowing paths which may or may not exist:

  • Split the path on the OS's path separator
  • Resolve as many of those path components in the filesystem as possible
  • Append remaining components that couldn't be resolved
  • If the relative path between parent and child doesn't start with .. + path.sep and isn't .. then the parent path contains the child path

This all works, assuming that any nonexistent path components would be created using only directories and files (no symlinks). For example say your script needs to write only to whitelisted paths and you're accepting untrusted (user-supplied) filenames. You could create subdirectories using something like PHP's mkdir with $recursive = true to create the directory structure in one step, similar to this example.

Here is the code (not runnable until Stack Overflow supports Node.js), the important functions are resolveFileSystemPath() and pathContains():

const kWin32 = false;    const fs = require('fs');  const path = kWin32 ? require('path').win32 : require('path');    ////////// functions //////////    // resolves (possibly nonexistent) path in filesystem, assuming that any missing components would be files or directories (not symlinks)  function resolveFileSystemPath(thePath) {   let remainders = [];     for (    let parts = path.normalize(thePath).split(path.sep); // handle any combination of "/" or "" path separators    parts.length > 0;    remainders.unshift(parts.pop())   ) {    try {     thePath =      fs.realpathSync(parts.join('/')) + // fs expects "/" for cross-platform compatibility      (remainders.length ? path.sep + remainders.join(path.sep) : ''); // if all attempts fail, then path remains unchanged       break;    } catch (e) {}   }     return path.normalize(thePath);  }    // returns true if parentPath contains childPath, assuming that any missing components would be files or directories (not symlinks)  function pathContains(parentPath, childPath, resolveFileSystemPaths = true) {   if (resolveFileSystemPaths) {    parentPath = resolveFileSystemPath(parentPath);    childPath = resolveFileSystemPath(childPath);   }     const relativePath = path.relative(parentPath, childPath);     return !relativePath.startsWith('..' + path.sep) && relativePath != '..';  }    ////////// file/directory/symlink creation //////////    console.log('directory contents:');    console.log();    try {   fs.mkdirSync('parent');  } catch (e) {} // suppress error if already exists    fs.writeFileSync('parent/child.txt', 'Hello, world!');    try {   fs.mkdirSync('outside');  } catch (e) {} // suppress error if already exists    try {   fs.symlinkSync(path.relative('parent', 'outside'), 'parent/child-symlink');  } catch (e) {} // suppress error if already exists    fs.readdirSync('.').forEach(file => {   const stat = fs.lstatSync(file);     console.log(    stat.isFile()     ? 'file'     : stat.isDirectory() ? 'dir ' : stat.isSymbolicLink() ? 'link' : '    ',    file   );  });  fs.readdirSync('parent').forEach(file => {   file = 'parent/' + file;     const stat = fs.lstatSync(file);     console.log(    stat.isFile()     ? 'file'     : stat.isDirectory() ? 'dir ' : stat.isSymbolicLink() ? 'link' : '    ',    file   );  });    ////////// tests //////////    console.log();    console.log(   "path.resolve('parent/child.txt'):       ",   path.resolve('parent/child.txt')  );  console.log(   "fs.realpathSync('parent/child.txt'):    ",   fs.realpathSync('parent/child.txt')  );  console.log(   "path.resolve('parent/child-symlink'):   ",   path.resolve('parent/child-symlink')  );  console.log(   "fs.realpathSync('parent/child-symlink'):",   fs.realpathSync('parent/child-symlink')  );    console.log();    console.log(   'parent contains .:                                ',   pathContains('parent', '.', true)  );  console.log(   'parent contains ..:                               ',   pathContains('parent', '..', true)  );  console.log(   'parent contains parent:                           ',   pathContains('parent', 'parent', true)  );  console.log(   'parent contains parent/.:                         ',   pathContains('parent', 'parent/.', true)  );  console.log(   'parent contains parent/..:                        ',   pathContains('parent', 'parent/..', true)  );  console.log(   'parent contains parent/child.txt (unresolved):    ',   pathContains('parent', 'parent/child.txt', false)  );  console.log(   'parent contains parent/child.txt (resolved):      ',   pathContains('parent', 'parent/child.txt', true)  );  console.log(   'parent contains parent/child-symlink (unresolved):',   pathContains('parent', 'parent/child-symlink', false)  );  console.log(   'parent contains parent/child-symlink (resolved):  ',   pathContains('parent', 'parent/child-symlink', true)  );

Output:

directory contents:  file .bash_logout file .bashrc file .profile file config.json dir  node_modules dir  outside dir  parent link parent/child-symlink file parent/child.txt  path.resolve('parent/child.txt'):        /home/runner/parent/child.txt fs.realpathSync('parent/child.txt'):     /home/runner/parent/child.txt path.resolve('parent/child-symlink'):    /home/runner/parent/child-symlink fs.realpathSync('parent/child-symlink'): /home/runner/outside  parent contains .:                                 false parent contains ..:                                false parent contains parent:                            true parent contains parent/.:                          true parent contains parent/..:                         false parent contains parent/child.txt (unresolved):     true parent contains parent/child.txt (resolved):       true parent contains parent/child-symlink (unresolved): true parent contains parent/child-symlink (resolved):   false 

Live example: https://repl.it/repls/LawngreenWorriedGreyware

The last line of the output is the important one, showing how resolved filesystem paths lead to the correct result (unlike the unresolved result above it).

Limiting filesystem reads/writes to certain directories is so important for security that I hope Node.js incorporates this functionality into their builtins. I haven't tested this on a native Windows box so please let me know if the kWin32 flag is working. I'll try to curate this answer as time allows.

</div
 
 
1
 
vote
&#038ベースの

;改善されたドムVinyardのコード:

<事前> <コード> const path = require('path'); function isAncestorDir(papa, child) { const papaDirs = papa.split(path.sep).filter(dir => dir!==''); const childDirs = child.split(path.sep).filter(dir => dir!==''); return papaDirs.every((dir, i) => childDirs[i] === dir); }

結果:

<事前> <コード> ..0
 

Based on & improved Dom Vinyard's code:

const path = require('path');  function isAncestorDir(papa, child) {     const papaDirs = papa.split(path.sep).filter(dir => dir!=='');     const childDirs = child.split(path.sep).filter(dir => dir!=='');      return papaDirs.every((dir, i) => childDirs[i] === dir); } 

Result in:

assert(isAncestorDir('/path/to/parent', '/path/to/parent/and/child')===true); assert(isAncestorDir('/path/to/parent', '/path/to')===false); assert(isAncestorDir('/path/to/parent', '/path/to/parent')===true); 
</div
 
 
1
 
vote

これは本当に古い質問ですが、私は、この使用して、ノードの<のhref =「https://nodejs.org/api/path.html#path_path_relative_from_to」のrel = "nofollowを内蔵のための本当に簡単な解決策を考え出しました> path.relative の "noreferrer。子供は親の中にある場合は、子からの相対パスは、常に<コード> ..1 が始まります。シンプルな

<事前> <コード> ..2
 

This is a really old question, but I came up with a really simple solution for this using node's built in path.relative. If the child is inside of parent the relative path from the child to the will always start with ... Simple.

import { relative } from 'path';  function isSubDirectory(parent, child) {   return relative(child, parent).startsWith('..'); } 
</div
 
 
     
     
1
 
vote

すでに答えている人に気付かれずに渡すように見える公演、およそべきものケア、親のパスとサブパスを開始するには十分であるべきかどうかをチェックます。

<事前> <コード> ..3
 

Should one care about performances, which seem to pass unnoticed to people who have already answered, check whether the sub path starts with its parent path should be enough.

const path = require('path');  function isSubPathOf(subPath, parentPath) {      parentPath = normalize(parentPath);      if (subPath.length <= parentPath.length)         return false;      function normalize(p) {          p = path.normalize(p);          if (!p.endsWith(path.sep))             p += path.sep;          return p;     }      subPath = normalize(subPath);      return subPath.startsWith(parentPath); }  console.log(isSubPathOf('/a/b/c/d/e', '/a/b/c')); console.log(isSubPathOf('/a/b/c/de', '/a/b/c')); console.log(isSubPathOf('/a/b/c', '/a/y/c')); console.log(isSubPathOf('/a/y/c/k', '/a/y/c')); 
</div
 
 
         
         
1
 
vote

Regexで実行するのは、それを行く1つの方法です(イベントリスナーを持つすべてのパスに対して、公開されたトピックがそのパスで起動したかどうかを確認してください)がありますが、それはあなたが持っているより多くの異なるパスを持つ可能性が高いため、不条理的に長いURL、発行されたトピックを破る可能性が高いかもしれません。

これはおそらく読むのが簡単です:

編集:/ stackoverflow.com/users/4771854/huaoguo"> @huaoguo は間違いなく正しい、 indexOf === 0 私たちが本当に必要なすべてです!

<事前> <コード> let paths = [ 'test', 'replyer/request', 'test/replyer/request' ] let topic = 'test/replyer/request/@issuer' let respondingPaths = (paths, topic) => paths.filter(path => topic.indexOf(path) === 0) console.log(respondingPaths(paths, topic)) // ['test', 'test/replyer/request']
 

Doing it with regex is one way to go about it (for every path that has an event listener, check whether the published topic starts with that path), but since it's more likely you'll have many different paths than you having absurdly long URLs, breaking down the published topic might be more efficient.

Something like this is probably easier to read, too:

Edit: @huaoguo is definitely right, indexOf === 0 is all we really need!

let paths = [     'test',     'replyer/request',     'test/replyer/request' ]  let topic = 'test/replyer/request/@issuer'  let respondingPaths = (paths, topic) => paths.filter(path => topic.indexOf(path) === 0)  console.log(respondingPaths(paths, topic)) // ['test', 'test/replyer/request'] 
</div
 
 
 
 
0
 
vote

@ DOM-Vinyardのアイデアは良いですが、コードは正しく機能していません、たとえばこの入力に:

<事前> <コード> isChildOf('/x/y', '/x') //false

私はここで私自身のバージョンを書きました:

<事前> <コード> function isParentOf(child, parent) { const childTokens = child.split('/').filter(i => i.length); const parentTokens = parent.split('/').filter(i => i.length); if (parentTokens.length > childTokens.length || childTokens.length === parentTokens.length) { return false; } return childTokens .slice(0, parentTokens.length) .every((childToken, index) => parentTokens[index] === childToken); }
 

@dom-vinyard's idea is good but code is not working correctly, for instance with this input:

isChildOf('/x/y', '/x') //false 

I wrote my own version here:

function isParentOf(child, parent) {   const childTokens = child.split('/').filter(i => i.length);   const parentTokens = parent.split('/').filter(i => i.length);    if (parentTokens.length > childTokens.length || childTokens.length === parentTokens.length) {     return false;   }    return childTokens     .slice(0, parentTokens.length)     .every((childToken, index) => parentTokens[index] === childToken); } 
</div
 
 
0
 
vote

<コード> indexOf (または比較文字列を比較する)を使用する別の解決策。
関数では、をサポートする複数のパス区切り文字をサポートするために、 indexOf を使用しませんでした。確認できますが、必ずが1つの場合、 indexOf を問題なく使用できます。
トリックは、区切り文字で終わるかどうかの場合、そのような区切り文字をそれに追加するだけで、そのような区切り記号を追加するだけです。その中で、子パス内の完全な経路ではない部分文字列を持つという問題はありません。 [<コード>および<コード> /this/isme ]( indexOf が偽の場合は、最初は子の子です。)このようなトリックを使ってこの[ let paths = [ 'test', 'replyer/request', 'test/replyer/request' ] let topic = 'test/replyer/request/@issuer' let respondingPaths = (paths, topic) => paths.filter(path => topic.indexOf(path) === 0) console.log(respondingPaths(paths, topic)) // ['test', 'test/replyer/request'] 0 let paths = [ 'test', 'replyer/request', 'test/replyer/request' ] let topic = 'test/replyer/request/@issuer' let respondingPaths = (paths, topic) => paths.filter(path => topic.indexOf(path) === 0) console.log(respondingPaths(paths, topic)) // ['test', 'test/replyer/request'] 1 ]を使用して、同じ let paths = [ 'test', 'replyer/request', 'test/replyer/request' ] let topic = 'test/replyer/request/@issuer' let respondingPaths = (paths, topic) => paths.filter(path => topic.indexOf(path) === 0) console.log(respondingPaths(paths, topic)) // ['test', 'test/replyer/request'] 2 を使用して比較すると、問題はありません。 ]。
Optionがある場合は、Option(ChildまたはEqual)を確認するために、それが3番目のオプションのパラメータです。

コードをチェックしてください。

<事前> <コード> let paths = [ 'test', 'replyer/request', 'test/replyer/request' ] let topic = 'test/replyer/request/@issuer' let respondingPaths = (paths, topic) => paths.filter(path => topic.indexOf(path) === 0) console.log(respondingPaths(paths, topic)) // ['test', 'test/replyer/request'] 3

ここではテスト例:

<事前> <コード> let paths = [ 'test', 'replyer/request', 'test/replyer/request' ] let topic = 'test/replyer/request/@issuer' let respondingPaths = (paths, topic) => paths.filter(path => topic.indexOf(path) === 0) console.log(respondingPaths(paths, topic)) // ['test', 'test/replyer/request'] 4

最後の例では、その関数を使用した機能を使用して子供や等しいところで確認してください(これは本当に一握りになる可能性があります)。

もまたあなたが私の2つの関連するGithub Reposをチェックすることができます。これは、分割メソッド(Regexエンジンを使用せずに複数の区切り文字を含む分割方法)、このメソッドも含まれています。コード内のコメントを確認してください):

  • https://github.com/mohamedlamineallal/ispathchildofjs
  • https://github.com/mohamedlamineallal/splitstrjs
 

Here another solution that use indexOf (or that work by comparing strings).
In the function bellow i didn't use indexOf in order to support multiple path separators. You can check, but if you are sure you have just one separator, you can use indexOf with no problem.
The trick is to check if the path end with a separator, if not you just add such a separator to it. In that, there will be no problem of having a substring that is not a complete path in the child path. [/this/isme_man and /this/isme] (the first is child of the second, if we simply use indexOf (which of course if false), but if you do using the trick like this [/this/isme/ and /this/isme_man/] and you compare using same indexOf there will be no problem, and it work nikel)].
Notice too that there is an option, to allow a check with orEqual (a child or equal), it's the third optional parameter.

Check the code bellow.

const PATH_SEPA = ['\', '/'];  function isPathChildOf(path, parentPath, orEqual) {     path = path.trim();     parentPath = parentPath.trim();      // trick: making sure the paths end with a separator     let lastChar_path = path[path.length - 1];     let lastChar_parentPath = path[parentPath.length - 1];     if (lastChar_parentPath !== '\' && lastChar_parentPath !== '/') parentPath += '/';     if (lastChar_path !== '\' && lastChar_path !== '/') path += '/';      if (!orEqual && parentPath.length >= path.length) return false; // parent path should be smaller in characters then the child path (and they should be all the same from the start , if they differ in one char then they are not related)      for (let i = 0; i < parentPath.length; i++) {         // if both are not separators, then we compare (if one is separator, the other is not, the are different, then it return false, if they are both no separators, then it come down to comparaison, if they are same nothing happen, if they are different it return false)         if (!(isPathSeparator(parentPath[i]) && isPathSeparator(path[i])) && parentPath[i] !== path[i]) {             return false;         }     }     return true; }  function isPathSeparator(chr) {     for (let i = 0; i < PATH_SEPA.length; i++) {         if (chr === PATH_SEPA[i]) return true;     }     return false; } 

Here a test example:

let path = '/ok/this/is/the/path'; let parentPath = '/ok/this/is'; let parentPath2 = '/ok/this/is/'; let parentPath3 = '/notok/this/is/different';  console.log("/ok/this/is/the/path' is child of /ok/this/is => " + isPathChildOf(path, parentPath)); console.log("/ok/this/is/the/path' is child of /ok/this/is/=> " + isPathChildOf(path, parentPath2)); console.log("/ok/this/is/' is child of /ok/this/is/ => " + isPathChildOf(parentPath2, parentPath2)); console.log("/ok/this/is/the/path' is child of /notok/this/is/different => " + isPathChildOf(path, parentPath3));  // test number 2:  console.log('test number 2 : '); console.log("=============================");  let pthParent = '/look/at/this/path'; let pth = '/look/at/this/patholabi/hola'; // in normal use of indexof it will return true (know too we didn't use indexof just to support the different path separators, otherwise we would have used indexof in our function)  //expected result is false console.log(`${pth}  is a child of ${pthParent}  ===>  ${isPathChildOf(pth, pthParent)}`);   let pthParent2 = '/look/at/this/path'; let pth2 = '/look/at/this/path/hola';   //expected result is true console.log(`${pth2}  is a child of ${pthParent2}  ===>  ${isPathChildOf(pth2, pthParent2)}`);   let pthParent3 = '/look/at/this/path'; let pth3 = '/look/at/this/pathholabi';   //expected result is false console.log(`${pth3}  is a child of ${pthParent3}  ===>  ${isPathChildOf(pth3, pthParent3)}`);  // test 3: equality console.log(' test 3 : equality'); console.log("==========================");  let pParent =  "/this/is/same/Path"; let p =  "/this\is/same/Path/";  console.log(`${p} is child of  ${pParent}   ====> ${isPathChildOf(p, pParent, true)}`); 

You can see in the last example how we used the function to check for both being a child or equal (which can be really handful).

Also know that, You can check my two related github repos, that include too another implementation for the split method (a spliting method with multiple separator without using the regex engine)), also this method too, and some good explanation (check the comments within the codes):

  • https://github.com/MohamedLamineAllal/isPathChildOfJS
  • https://github.com/MohamedLamineAllal/splitStrJS
</div
 
 
-5
 
vote

let paths = [ 'test', 'replyer/request', 'test/replyer/request' ] let topic = 'test/replyer/request/@issuer' let respondingPaths = (paths, topic) => paths.filter(path => topic.indexOf(path) === 0) console.log(respondingPaths(paths, topic)) // ['test', 'test/replyer/request'] 5 を使用して、子ディレクトリへのパスが親ディレクトリへのパスで始まることを確認するには、

<事前> <コード> indexOf16
 

Use indexOf to check that the path to the child directory starts with the path to the parent directory is enough:

function isParentOf(parent, dir) {     return dir.indexOf(parent) === 0; }  isParentOf('test/replyer/request/@issuer', 'test') // true isParentOf('test/replyer/request/@issuer', 'replyer/request') // false isParentOf('test/replyer/request/@issuer', 'test/replyer/request') // true 
</div
 
 
     
     

関連する質問

6  nodejsとnode-mongodb-native  ( Nodejs and node mongodb native ) 
ノードを始めて、Mongoドライバを手に入れようとしている 仕事に。私は自分の接続を設定しました、そして奇妙なことに私は物事を挿入することができます ちょうどいいですが、コレクションの検索を呼び出して狂気が発生します。 <事前> <コード> var db = ...

0  isi日付をJSのISOに変換する方法  ( How to convert isi date to iso in js ) 
私は日付をになっています <事前> <コード> data.created = "Wed May 03 2017 15:41:49 GMT 0530(IST)" それを変換したいのです 通常のISIフォーマット <事前> <コード> 2017-03...

0  私の約束に何が間違っているか、非同期/ await関数の両方が空の配列を返しています  ( Whats wrong with my promise async await function both are returning empty arrays ) 
私のコードには、以下に示すようなオブジェクトの配列があります <事前> <コード> [ { name: 'JMCP', priority: 1 }, { name: 'OTC', priority: 2 }, { name: 'CMT', priori...

0  async.eachseriesは私にrangeerrorを与えます:最大呼び出しスタックを超えました  ( Async eachseries gives me an rangeerror maximum call stack exceeded ) 
コレクションで4435以上の製品を繰り返したいです。すべての製品に対して、イメージをダウンロードしてAmazon S3バケットにアップロードします。最後の部分では、問題がうまく機能しているのか機能を書いたことがあります。 しかし750の製品の後にNode.j...

498  ノード/ Express:EADdrinuse、既に使用中のアドレス - Kill Server  ( Node express eaddrinuse address already in use kill server ) 
connect:を使ってnode.jsで稼働している単純なサーバーを持っています <事前> <コード> var server = require('connect').createServer(); //actions... server.listen(30...

2  PDFとしてデータベースからバッファデータをロードします  ( Loading buffer data from database as pdf ) 
私はユーザーがPDFファイルをアップロードできるWebアプリケーションを開発しています。その後、後でそれを取得して表示します。これを実現してきたことは、PDFがPostgreSQLデータベースにByteaデータ型としてアップロードされている(列は「添付ファイル...

14  'React-Admin'アプリケーションをデプロイするときに、Heroku Serverは "JavaScriptヒープをout memory up out"でクラッシュします  ( Heroku server crashes with javascript heap out of memory when deploying react ) 
現在、私のローカルでうまく機能する 'React-admin'を使用して管理パネルを開発していますが、私がHerokuにアプリをアップロードするとすぐに、ビルドは次のエラーで失敗します。 "致命的なエラー:無効なマークコンパクトヒープ制限割り当ての近くに失敗し...

0  HTMLを生成するか、それをNodeJSの世界にロードしますか?  ( Generate html or load it in nodejs world ) 
あなたのためのNOOBの質問であるNodeJSの世界に新しい:HAML、EJS、...を使用してHTMLファイルを生成します。通常のようなHTMLファイルをロードできますか?どちらの方法も効率的ですか? 注:私はここに悪い質問をしていると思いますが、それは明...

122  nodejs - URLをリダイレクトします  ( Nodejs redirect url ) 
無効なURLを入力したときに、Node.jsサーバを404.htmlページにリダイレクトする方法を得るには? 私はいくつかの検索をしました、そしてそれはほとんどの結果が表現のためのものですが、私は純粋なnode.jsに私のサーバーを書きたいようです。 ...

2  Node.js Web Sockets Server:データ管理が安定/スケーラブルのための私の考えですか?  ( Node js web sockets server is my idea for data management stable scalable ) 
クライアントデータ転送用のWebソケットプラグインを使用して、バックエンドで実行されているNode.jsを搭載したHTML5ブラウザのマルチプレイヤーRPGを開発しています。私が直面している問題は、このプロセスを想像することができるように、このプロセスを想像す...




© 2022 cndgn.com All Rights Reserved. Q&Aハウス 全著作権所有