コメント除去 + 関数リストアップ


const fs = require('fs');
const path = require('path');

function removeComments(code) {
  const lines = code.split(/(?<=\n)/g);
  const result = [];
  let inMultilineComment = false;
  let inLiteralDoubleQuote = false;
  let inLiteralSingleQuote = false;

  for (const line of lines) {
    let processedLine = '';
    let inComment = false;

    for (let i = 0; i < line.length; i++) {
      const char = line[i];

      if (inMultilineComment) {
        // マルチラインコメントモード
        if (char === '*' && line[i + 1] === '/') {
          // 終端検出
          inMultilineComment = false;
          i++; // /ぶんをスキップ
        } else if (char === '\n') {
          // コメント継続中は改行コードのみ行末に追加
          processedLine += char;
        }
      } else if (inComment) {
        // シングルラインコメントモード
        if (char === '\n') {
          processedLine += char;
          inComment = false;
        }
      } else if (inLiteralDoubleQuote) {
        processedLine += char;
        if (char === '"' && ((i == 0) || line[i - 1] !== '\\')) {
          inLiteralDoubleQuote = false;
        }
      } else if (inLiteralSingleQuote) {
        processedLine += char;
        if (char === "'" && ((i == 0) || line[i - 1] !== '\\')) {
          inLiteralSingleQuote = false;
        }
      } else {
        if (char === '/' && line[i + 1] === '/') {
          inComment = true;
          i++;
        } else if (char === '/' && line[i + 1] === '*') {
          inMultilineComment = true;
          i++;
        } else if (char === '"') {
          inLiteralDoubleQuote = true;
          processedLine += char;
        } else if (char === "'") {
          inLiteralSingleQuote = true;
          processedLine += char;
        } else {
          processedLine += char;
        }
      }
    }

    if (processedLine.length > 0 || inMultilineComment) {
      result.push(processedLine);
    }
  }
  return result
}

function extractFunctions(lines) {
  //  const lines = code.split(/\n/g);
  const result = [];
  let currentFunctionName = '';
  let startLine = -1;
  let endLine = -1;
  let inString = false;
  let stringStartChar = '';
  let depth = 0;

  for (let i = 0; i < lines.length; i++) {
    const line = lines[i];

    // 関数定義かどうかを判定(リテラル内は無視)
    const regex = /function\s+(\w+)\s*\(/;
    const match = line.match(regex);
    if (match && depth === 0 && !inString) {
      currentFunctionName = match[1];
      startLine = i + 1;
      depth = 1;
    }

    // 関数{}の開始と終了判定
    for (let j = 0; j < line.length; j++) {
      const char = line[j];
      if ((char === '"' || char === '`') && !inString) {
        inString = true;
        stringStartChar = char;
      } else if (char === stringStartChar && inString) {
        inString = false;
      } else if (!inString) {
        if (char === '{') {
          depth++;
        } else if (char === '}') {
          depth--;
          if (depth === 1) {
            endLine = i + 1;
            result.push(`${currentFunctionName},${startLine},${endLine}`);
            currentFunctionName = '';
            depth = 0;
          }
        }
      }
    }
  }

  return result.join('\n');
}

function main() {
  // 処理対象のファイルパスを指定
  const filePath = path.join(__dirname, 'example.js');

  // ファイルを読み込む
  const code = fs.readFileSync(filePath, 'utf8');
  const code_linux = code.replace(/\r\n/g, '\n');
  // コメントを削除
  const lines_without_comments = removeComments(code_linux);
  // 結果を出力
  const functions = extractFunctions(lines_without_comments);
  console.log(functions);
}

main();

コメント除去

function removeComments(code) {
  const lines = code.split(/(?<=:)/g);
  const result = [];
  let inMultilineComment = false;
  let inLiteralDoubleQuote = false;
  let inLiteralSingleQuote = false;

  for (const line of lines) {
    let processedLine = '';
    let inComment = false;

    for (let i = 0; i < line.length; i++) {
      const char = line[i];

      if (inMultilineComment) {
        // マルチラインコメントモード
        if (char === '*' && line[i + 1] === '/') {
          // 終端検出
          inMultilineComment = false;
          i++; // /ぶんをスキップ
        } else if (char === '\n') {
          // コメント継続中は改行コードのみ行末に追加
          processedLine += char;
        }
      } else if (inComment) {
        // シングルラインコメントモード
        if (char === '\n') {
          processedLine += char;
          inComment = false;
        }
      } else if (inLiteralDoubleQuote) {
        processedLine += char;
        if (char === '"' && ((i == 0) || line[i - 1] !== '\\')) {
          inLiteralDoubleQuote = false;
        }
      } else if (inLiteralSingleQuote) {
        processedLine += char;
        if (char === "'" && ((i == 0) || line[i - 1] !== '\\')) {
          inLiteralSingleQuote = false;
        }
      } else {
        if (char === '/' && line[i + 1] === '/') {
          inComment = true;
          i++;
        } else if (char === '/' && line[i + 1] === '*') {
          inMultilineComment = true;
          i++;
        } else if (char === '"') {
          inLiteralDoubleQuote = true;
          processedLine += char;
        } else if (char === "'") {
          inLiteralSingleQuote = true;
          processedLine += char;
        } else {
          processedLine += char;
        }
      }
    }

    if (processedLine.length > 0 || inMultilineComment) {
      result.push(processedLine);
    }
  }

  return result.join('\n');
}

const fs = require('fs');
const path = require('path');

function main() {
  // 処理対象のファイルパスを指定
  const filePath = path.join(__dirname, 'example.js');

  // ファイルを読み込む
  const code = fs.readFileSync(filePath, 'utf8');
  const code_linux = code.replace(/\r\n/g, '\n');
  //console.log(code_linux);

  // コメントを削除
  const codeWithoutComments = removeComments(code_linux);

  // 結果を出力
  console.log(codeWithoutComments);
}

main();

import re

def split_data(input_str):
    pattern = r"(\d+?)\s*:(.*?)[,\s]"
    results = []
    for match in re.finditer(pattern, input_str):
        num = match.group(1)
        data = match.group(2)
        results.append((num, data))
    return results

# 使用例
input_str = "0:aa,bb,dd,dd,1:ee,ff,gg,2:hh...., 3 :ii,jj,kk"
output = split_data(input_str)
for num, data in output:
    print(f"Number: {num}, Data: {data}")

文字列分割

python学習


import lxml.etree as etree
# 追加・更新関数

class PathManipulator:
    @staticmethod
    def custom_split(xpath, sep='/'):
        result = []
        in_quotes = False
        start = 0

        for i, char in enumerate(xpath):
            if char in ('"', "'"):
                in_quotes = not in_quotes
            elif char in sep and not in_quotes:
                result.append(xpath[start:i])
                start = i + 1

        result.append(xpath[start:])
        return [x for x in result if x]  # 空文字列を除外する

    @staticmethod
    def strncmp(s1, s2, n):
        len1 = len(s1)
        len2 = len(s2)
        min_len = min(len1, len2, n)

        for i in range(min_len):
            if s1[i] != s2[i]:
                return ord(s1[i]) - ord(s2[i])

        if min_len < n:
            return len1 - len2
        else:
            return 0

    @staticmethod
    def split_except_literal(input_string, separator):
        result = []
        temp = ""
        skip_count = 0
        separetor_len = len(separator)
        literal_started = False
        for i, char in enumerate(input_string):
            separator_candidate = PathManipulator.extract_string(
                input_string, i, separetor_len)
            if skip_count > 0:
                skip_count -= 1
                continue
            if char == "'":
                literal_started = not literal_started
                temp += char
            elif PathManipulator.strncmp(separator_candidate, separator, separetor_len) == 0 and not literal_started:
                skip_count = separetor_len - 1
                result.append(temp)
                temp = ""
            else:
                temp += char
        if temp:
            result.append(temp)
        return result

    @staticmethod
    def extract_string(string, start_index, length):
        return string[start_index:start_index + length]


# 追加・更新関数

class XmlManipulator:
    def __init__(self, filepath):
        self.filepath = filepath
        self. parser = etree.XMLParser(remove_blank_text=True)
        self.tree = etree.parse(self.filepath, self.parser)
        self.root = self.tree.getroot()

    def upsert(self, xpath):
        parts = PathManipulator.custom_split(xpath)
        current_element = self.root
        query = "."

        for i, part in enumerate(parts):
            if (part == "."):
                continue

            # タグ名と属性([]をひとかたまりの文字列として扱う)取得する
            tag_name, *attributes_string = PathManipulator.custom_split(part, '[]')
            print(attributes_string)
            print(part + " -> " + tag_name + " -> " + str(attributes_string))
            tag_name = tag_name.strip()
            attributes_string_internal = " ".join(attributes_string).strip()
            attributes_string = ""
            if len(attributes_string_internal) is not 0:
                attributes_string = '[' + attributes_string_internal + ']'

            query = f"./{tag_name}{attributes_string}"
            elements = current_element.xpath(query)

            if not elements:
                # 要素が存在しない場合は新規作成する
                new_element = etree.SubElement(current_element, tag_name)

                # 属性を設定する
                for attribute in PathManipulator.split_except_literal(attributes_string_internal, 'and'):
                    attribute = attribute.strip()
                    key, value = attribute.split('=')
                    key = key.strip("@")
                    new_element.set(key.strip(), value.strip("]['\""))

                current_element = new_element
            else:
                # 要素が存在する場合はその要素を選択する
                print("Found: " + str(len(elements)) +
                      " elements for the given XPath = " + query)
                current_element = elements[0]

        return current_element

    # 削除関数

    def delete(self, xpath):
        elements = self.root.xpath(xpath)
        if len(elements) > 1:
            print("Warning: Multiple elements found for the given XPath = " + xpath)
        elif len(elements) == 1:
            parent = elements[0].getparent()
            parent.remove(elements[0])
        else:
            print("Warning: No elements found for the given XPath = " + xpath)

    def save(self,  filepath):
        # 名前空間を削除して保存する
        for elem in self.root.iter():
            elem.tag = etree.QName(elem).localname
        # インデントを行う
        tree = self.root.getroottree()
        tree.write(filepath, pretty_print=True,
                   encoding='utf-8', xml_declaration=True)


# テスト用のコード
if __name__ == "__main__":
    xml_mod =XmlManipulator('input.xml')
    # 追加・更新のテスト
    # ない場合は新規作成
    xml_mod.upsert(
        "./base[@class='hogeC' and @distName='/aaa/bbb-99/fff-2/ddd-1/']")
    # ない場合は新規作成
    xml_mod.upsert(
        "./base[@class='hogeC' and @distName='/aaa/bbb-99/fff-2/ddd-4/']")
    # ない場合は新規作成
    xml_mod.upsert(
        "./base[@class='hogeC' and @distName='/aaa/eee-99/fff-2/ddd-4/']")
    element = xml_mod.upsert(
        "./base[@class='hogeA' and @distName='/aaa/bbb-99/ccc-5/ddd-1/']/list[@name='hogeList']/p")
    element.text = "hoge1"
    element = xml_mod.upsert(
        "./base[@class='hogeA' and @distName='/aaa/bbb-99/ccc-5/ddd-1/']/list[@name='hogeList']/p")
    element.text = "hoge2"
    element = xml_mod.upsert(
        "./base[@class='hogeA' and @distName='/aaa/bbb-99/ccc-5/ddd-1/']/list[@name='hogeList']/p")
    element.text = "hoge3"
    element = xml_mod.upsert(
        "./base[@class='hogeA' and @distName='/aaa/bbb-99/ccc-5/ddd-1/']/list[@name='hogeList']/p")
    element.text = "hoge4"
    element = xml_mod.upsert(
        "./base[@class='hogeA' and @distName='/aaa/bbb-99/ccc-5/ddd-1/']/list[@name='hogeList']/p")
    element.text = "hoge5"
    xml_mod.upsert("./base[@class='hogeA']")  # ある場合は取得
    # 削除のテスト
    xml_mod.delete("./base[@class='hogeC']")  # 削除する場合
    xml_mod.delete("./base[@class='hogeD']")  # 存在しない場合

    # 保存のテスト
    xml_mod.save( "output.xml")

import csv
import os


class CSVFileManager:
    def __init__(self, file_path, title_row_index=0, primary_keys=None):
        self.file_path = file_path
        self.title_row_index = title_row_index
        self.primary_keys = primary_keys or []
        self.data = self._read_csv()

    def _read_csv(self):
        with open(self.file_path, 'r', newline='') as file:
            reader = csv.reader(file)
            data = list(reader)
        return data

    def save(self, file_path=None):
        file_path = file_path or self.file_path
        with open(file_path, 'w', newline='') as file:
            writer = csv.writer(file)
            writer.writerows(self.data)

    def upsert(self, new_row):
        title_row = self.data[self.title_row_index]
        
        # Check if primary keys are provided
        if not self.primary_keys:
            raise ValueError("Primary keys not specified.")
        
        # Find index of primary key columns
        key_indices = [title_row.index(key) for key in self.primary_keys]
        
        # Check for duplicate primary keys
        for row in self.data[self.title_row_index + 1:]:
            if all(row[idx] == new_row[title_row.index(title)] for idx, title in zip(key_indices, self.primary_keys)):
                raise ValueError("Duplicate primary keys found.")
        
        # Upsert or append the new row
        for idx, row in enumerate(self.data[self.title_row_index + 1:], start=self.title_row_index + 1):
            if all(row[idx] == new_row[title_row.index(title)] for idx, title in zip(key_indices, self.primary_keys)):
                self.data[idx] = new_row
                break
        else:
            self.data.append(new_row)

    def delete(self, key_values):
        title_row = self.data[self.title_row_index]
        
        # Check if primary keys are provided
        if not self.primary_keys:
            raise ValueError("Primary keys not specified.")
        
        # Find index of primary key columns
        key_indices = [title_row.index(key) for key in self.primary_keys]
        
        # Find rows with matching primary keys
        matching_rows = []
        for idx, row in enumerate(self.data[self.title_row_index + 1:], start=self.title_row_index + 1):
            if all(row[idx] == value for idx, value in zip(key_indices, key_values)):
                matching_rows.append(idx)
        
        # Error if no matching rows found
        if not matching_rows:
            print("Warning: No rows found with specified primary keys.")
            return
        
        # Error if multiple matching rows found
        if len(matching_rows) > 1:
            raise ValueError("Multiple rows found with specified primary keys.")
        
        # Delete matching row
        del self.data[matching_rows[0]]


# Example usage:
file_path = "example.csv"
primary_keys = ["ID"]

# Initialize CSVFileManager instance
manager = CSVFileManager(file_path, title_row_index=3, primary_keys=primary_keys)

# Upsert a new row
new_row = ["123", "John Doe", "30"]
manager.upsert(new_row)

# Delete a row
manager.delete(["123"])

# Save changes to file
manager.save()
import pandas as pd
import csv


def custom_split(csv_line, sep=',', strip=True):
    result = []
    in_quotes = False
    start = 0

    for i, char in enumerate(csv_line):
        if char in ('"', "'"):
            in_quotes = not in_quotes
        elif char in sep and not in_quotes:
            csv_value = csv_line[start:i]
            if strip:
                csv_value = csv_value.strip()
            csv_value = remove_outer_quotes(csv_value)
            result.append(csv_value)
            start = i + 1

    csv_value = csv_line[start:]
    if strip:
        csv_value = csv_value.strip()
    result.append(csv_value)
    return [x for x in result if x]  # 空文字列を除外する


def remove_outer_quotes(s):
    if len(s) < 2 or (s[0] != s[-1]) or (s[0] not in ['"', "'"]):
        return s
    elif s.count(s[0]) >= 3:
        return s
    else:
        return s[1:-1]


class CustomCSVParser:
    def __init__(self, file_path, skiprows=3):
        self.data = []
        with open(file_path, 'r') as f:
            lines = f.readlines()
            self.titles = custom_split(lines[skiprows].strip())
            data_lines = lines[skiprows + 1:]
            for line in data_lines:
                line = line.strip()
                if line:
                    row = custom_split(line)
                    self.data.append(row)

    def convertToCsv(self, dn, list_val, param_name, value):
        try:
            dn_index = self.titles.index('DN')
            list_index = self.titles.index('list')
            param_index = self.titles.index('param abbreviated name')
            value_index = self.titles.index('value')

            for row in self.data:
                row_list = row[list_index]
                print(len(row_list), len(list_val), len("''"))
                if row_list == list_val:
                    print("same!")
                if row[dn_index] == dn and row_list == list_val and row[param_index] == param_name:
                    values = row[value_index].split(',')
                    for val_pair in values:
                        key, val = val_pair.split(':')
                        if key == value:
                            return val
                    raise ValueError("Specified value not found in CSV.")
            raise ValueError("Specified combination not found in CSV.")
        except Exception as e:
            return str(e)

    def convertToCom(self, dn, list_val, param_name, value):
        try:
            row = self.data[(self.data['DN'] == dn) & (self.data['list'] == list_val) & (
                self.data['param abbreviated name'] == param_name)]
            if not row.empty:
                if value in row.values[0][4:]:
                    idx = row.values[0][4:].tolist().index(value) + 1
                    return row.columns[idx]
                else:
                    raise ValueError("Specified value not found in CSV.")
            else:
                raise ValueError("Specified combination not found in CSV.")
        except Exception as e:
            return str(e)


# Example usage:
converter = CustomCSVParser("stepdata.csv")
print(converter.convertToCsv("/aaa/bbb-/ccc-/ddd-",
      '', "data_name_1", "111"))  # Output: h2
print(converter.convertToCom("/aaa/bbb-/ccc-/ddd-",
      '', "data_name_1", "h2"))  # Output: 112

javascript で関数の行を取得する

const fs = require('fs');

// ファイルパスをコマンドライン引数から取得
//const filePath = process.argv[2];
const filePath = 'input.js';

if (!filePath) {
    console.error('ファイルパスが指定されていません。');
    process.exit(1);
}

// ファイル読み込み
fs.readFile(filePath, 'utf-8', (err, data) => {
    if (err) {
        console.error('ファイルの読み込み中にエラーが発生しました。', err);
        process.exit(1);
    }

    // 関数の正規表現
    const functionRegex = /function\s+(\w+)\s*\([^)]*\)\s*{[^}]*}/g;

    // マッチした結果をCSV形式で出力
    let match;
    let foundFunctions = false;

    while ((match = functionRegex.exec(data)) !== null) {
        foundFunctions = true;
        console.log(`${filePath}, ${match[1]}, ${getLineNumber(data, match.index)}, ${getLineNumber(data, match.index + match[0].length)}`);
    }

    if (!foundFunctions) {
        console.log(`${filePath}, (global), 1, ${getLineNumber(data, data.length)}`);
    }
});

// 行番号を取得するヘルパー関数
function getLineNumber(text, index) {
    return text.substring(0, index).split('\n').length;
}

for each => for

const fs = require('fs');

// ファイルパスをコマンドライン引数から取得
//const filePath = process.argv[2];
const filePath = 'input.js';

if (!filePath) {
  console.error('ファイルパスが指定されていません。');
  process.exit(1);
}

// ファイル読み込み
fs.readFile(filePath, 'utf-8', (err, data) => {
  if (err) {
    console.error('ファイルの読み込み中にエラーが発生しました。', err);
    process.exit(1);
  }

  // for each の正規表現
  //  const forEachRegex = /for each\s*\(\s*var\s+(\$\$\d+)\s+in\s+(\$\$\d+)\s*\)\s*\{/g;
  const forEachRegex = /for each\s*\(\s*var\s+([a-zA-Z_$][a-zA-Z0-9_$]*)\s+in\s+([a-zA-Z_$][a-zA-Z0-9_$]*)\s*\)(\s*)\{/g;

  // マッチした結果をES5形式に変換c
  const transformedCode = data.replace(forEachRegex, function (match, $$1, $$2, $$3) {
    const replacement = `for (var ${$$2}_key_ in ${$$2})${$$3}\{\nvar ${$$1} = ${$$2}[${$$2}_key_];`;
    return replacement;
  });

  // 変換結果を出力
  console.log(transformedCode);
});

CSVファイルパースと検索条件

const fs = require('fs');
const parse = require('csv-parser/lib/sync');

class CsvReader {
    constructor(filePath, hasHeader = true) {
        this.filePath = filePath;
        this.hasHeader = hasHeader;
    }

    readCsv() {
        try {
            const csvData = fs.readFileSync(this.filePath, 'utf8');
            const rows = parse(csvData, {
                skip_empty_lines: true,
                skip_lines_with_empty_values: true,
                ...(this.hasHeader && { headers: true }), // Include headers if hasHeader is true
            });
            return rows;
        } catch (error) {
            throw new Error(`Error reading CSV file: ${error.message}`);
        }
    }

    searchByColumnValues(conditions) {
        const data = this.readCsv();
        return data.filter((row) => {
            return conditions.every((condition) => {
                const [column, value] = Object.entries(condition)[0];
                return row[column] === value;
            });
        });
    }
}

// Usage example
const csvReader = new CsvReader('path/to/your/csv/file.csv', true); // Set hasHeader to true
const searchConditions = [
    { "Product": "Carrot" },
    { "Category": "Vegetables" }
];
const searchResults = csvReader.searchByColumnValues(searchConditions);
console.log('Matching rows:', searchResults);

htmlに動的にscriptを挿入するためのサンプル

htmlに動的にscriptを挿入するためのサンプル

first.js

function loading(scriptSrc) {
    var script = document.createElement('script');
    script.src = scriptSrc;
    document.head.appendChild(script);
}

loading('second.js');
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="first.js"></script>
</head>
<body>
  <!-- ここにコンテンツを追加 -->
</body>
</html>