gpt4 book ai didi

bash - 将单个文件脚本分解为具有适当目录布局的项目

转载 作者:行者123 更新时间:2023-11-29 09:31:15 25 4
gpt4 key购买 nike

问题

假设我写了一个冗长的脚本在某些语言中“lang”,现在想转换这个单文件脚本进入包含许多文件的项目的目录树。我想在这个文件中插入某种分隔符和文件路径,并以某种方式对其进行处理,以便最终获得:

  • 适当的项目目录布局(sth. like this) ,
  • 构建定义文件,
  • 自述文件,
  • main/srctest/src 等的单独子目录

例如,给定以下脚本(伪代码):

// required dependencies, should be moved
// into the build definition build.foo
require "org.foo" % "foo-core" % "1.2.3"
require "org.bar" % "bar-gui" % "3.2.1"

// A longer comment that should be converted
// into a text file and moved into a 'notes'
// subdirectory

/*
#README

Another lengthy comment that should go into
a readme.md
*/

/** A class that should
* go to src/main/lang/proj/A.lang
*/
class A {
def a = "foo"
}

/** Another class
* that should go to src/main/lang/proj/B.lang
*/
class B {
def b = "bar"
}

/** Some tests,
* should end up in
* src/test/lang/proj/MyTest.lang
@Test def testFoo() {
assert(2 + 2 == 5)
}

并假设我可以在这个文件中插入任意分隔符、命令、转义序列和文件路径,我想获得以下项目:

project/
|-- build.txt
|-- notes
| `-- note_01.txt
|-- readme.md
`-- src
|-- main
| `-- lang
| `-- proj
| |-- A.lang
| `-- B.lang
`-- test
`-- lang
`-- proj
`-- MySpec.lang

编辑:

接下来是我的 own answer below 的一个不太复杂的版本


我尝试过的

这是一种简单的方法:

  • 通过在 #!/bin/bash 之前将原始脚本转换为 bash 脚本
  • 将源代码拆分为 HEREDOCS
  • 在必要时插入包声明
  • 在 HEREDOC 部分之间添加一堆 mkdir -pcd
  • cat 将 HEREDOC 片段放入适当命名的文件中
  • 在空目录上测试脚本,直到它按预期工作

对于上面的脚本,它可能看起来像这样:

#!/bin/bash

mkdir project
cd project

cat <<'EOF' > build.txt
// required dependencies, should be moved
// into the build definition build.foo
require "org.foo" % "foo-core" % "1.2.3"
require "org.bar" % "bar-gui" % "3.2.1"
EOF

mkdir notes
cd notes
cat <<'EOF' > note_01.txt
// A longer comment that should be converted
// into a text file and moved into a 'notes'
// subdirectory
EOF
cd ..

cat <<'EOF' > readme.md
/*
#README

Another lengthy comment that should go into
a readme.md
*/
EOF

mkdir -p src/main/lang/proj
cd src/main/lang/proj
cat <<'EOF' > A.lang
package proj

/** A class
* that should go to src/main/lang/proj/A.lang
*/
class A {
def a = "foo"
}
EOF

cat <<'EOF' > B.lang
package proj
/** Another class
* that should go to src/main/lang/proj/B.lang
*/
class B {
def b = "bar"
}
EOF
cd ../../..

mkdir -p test/lang/proj
cd test/lang/proj
cat <<'EOF' > MySpec.lang
package proj

/** Some tests,
* should end up in
* src/test/lang/proj/MyTest.lang
@Test def testFoo() {
// this should end up in test
assert(2 + 2 == 5)
}
EOF
cd ../../..

这种方法有什么问题

它确实生成了正确的树,但这种方法似乎很容易出错:

  • 很容易cd ../../..到错误的嵌套级别
  • 很容易用错误的名称mkdir,然后无法cd 进入它。
  • 没有办法将整个树结构作为一个单独的对象来处理事务,也就是说,如果稍后脚本中出现某些问题,没有简单的方法来清理之前产生的困惑发生错误。

我当然可以尝试通过定义让它不那么脆弱mkdircd 的特殊功能,以及然后将这些函数的调用与 cat 一起包装到(mkdirAndCd d ; cat)

但感觉不太对劲。有没有更简单的怎么做?能否以某种方式结合标准的 bash/linux 实用程序变成一种微小且非常受限的领域特定语言用文本文件生成目录树?也许是 split 的一些较新版本,其中可以指定要拆分的位置以及放置碎片的位置?


相关问题:


其他有趣的提议但似乎行不通:

  • 使用 tar 。这意味着必须手动将文本文件转换为有效的 tar 存档。虽然 tar 存档确实 是一个纯文本文件,但它的 internal format对于这样一个简单的任务来说,它看起来不像是最舒适的 DSL。它从未打算以这种方式直接供人类使用。
  • shar 也有类似的论点。由于 shar 使用 bash 本身来提取存档,我的上述建议原则上是一个非常不常见格式的手动生成的 shar-archive,因此 shar 似乎共享上述建议的所有缺点。我更喜欢限制更多的东西,它允许做更少的事情,但对结果的质量提供更多保证。

也许我应该再次强调,我一开始并没有树,所以没有什么可压缩的。我只有一个脚本文件,并且对树最终应该是什么样子有一个粗略的想法。

最佳答案

在我看来,您正在尝试编写自定义解析器。如果您提到的所有 block 都以双行结尾结束,这可以帮助您

#!/bin/bash

gawk 'BEGIN{RS="\n\n([/][*]|[/]{2,2})"}
{
if ($0 ~ /#README/){
system("echo -e \"\nThis is a Readme.md\n--------\n" $0 "\"")
}else if ($0 ~ /class /){
system("echo -e \"\nThis is a class\n---------\n/*" $0 "\"")
}else if ($0 ~ /require /){
system("echo -e \"\nthis is a conf\n-----------\n" $0 "\"")
}else if($0 ~ /[/]{2,2}.*\n[/]{2,2}/){
system("echo -e \"\nthis is a note\n-----------\n" $0 "\"")
}

}' your_script.lang

关键部分是记录分隔符 RS,它将以 '\n\n//' 或 '\n\n/*' 开头的代码块分开。您可以为每种类型的 block 编写自定义脚本,而不是 echo -e。请注意,记录分隔符不会出现在 $0 上,因此您必须添加缺少的字符,如上面的/class/示例中所示。

上面代码的输出是

this is a conf
-----------
// required dependencies, should be moved
// into the build definition build.foo
require org.foo % foo-core % 1.2.3
require org.bar % bar-gui % 3.2.1

this is a note
-----------
A longer comment that should be converted
// into a text file and moved into a 'notes'
// subdirectory

This is a Readme.md
--------

#README

Another lengthy comment that should go into
a readme.md
*/

This is a class
---------
/** A class that should
* go to src/main/lang/proj/A.lang
*/
class A {
def a = foo
}

This is a class
---------
/** Another class
* that should go to src/main/lang/proj/B.lang
*/
class B {
def b = bar
}

关于您的疑虑:

  • 很容易将 ../../.. 复制到错误的嵌套级别-> 定义一个带有根路径的变量并 cd 到它。

  • 很容易用错误的名称 mkdir,然后无法 cd 进入。-> 用目录名定义变量并检查它们是否已经存在。

    path1=src/main/lang/some如果 [ -d $path1 ];然后 做一点事fi

  • 没有办法将整个树构建作为一个事务来处理......-> 写入您创建的每个新目录/文件的文件路径,并在必要时使用它来恢复。

关于bash - 将单个文件脚本分解为具有适当目录布局的项目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49036972/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com