1.概述

ChatGPT是一款由OpenAI推出的先进对话模型,其强大的自然语言处理能力使得它成为构建智能对话系统和人机交互应用的理想选择。为了进一步拓展ChatGPT的功能和适应不同领域的需求,OpenAI提供了插件开发平台,让开发者可以定制化和扩展ChatGPT的能力。

2.内容

OpenAI 插件将 ChatGPT 连接到第三方应用程序。这些插件使 ChatGPT 能够与开发人员定义的 API 进行交互,从而增强 ChatGPT 的功能并允许其执行广泛的操作。插件使 ChatGPT 能够执行以下操作:

  • 检索实时信息;例如,体育赛事比分、股票价格、最新新闻等。
  • 检索知识库信息;例如,公司文档、个人笔记等。
  • 协助用户采取行动;例如,预订航班、订餐等。

插件开发人员公开一个或多个 API 端点,并附有标准化清单文件和 OpenAPI 规范。这些定义了插件的功能,允许 ChatGPT 使用文件并调用开发人员定义的 API。

AI 模型充当智能 API 调用者。给定 API 规范和何时使用 API 的自然语言描述,模型会主动调用 API 来执行操作。例如,如果用户询问“我应该在巴黎哪里住几晚?”,模型可能会选择调用酒店预订插件 API,接收 API 响应,并结合 API 数据生成面向用户的答案及其自然语言能力。

2.1 插件流程

要构建插件,了解端到端流程是非常有必要的,流程如下所示:

  1. 创建清单文件并将其托管在yourdomain.com/.well-known/ai-plugin.json

    • 该文件包含有关您的插件的元数据(名称、徽标等)、有关所需身份验证的详细信息(身份验证类型、OAuth URL 等)以及您想要公开的端点的 OpenAPI 规范。
    • 该模型将看到 OpenAPI 描述字段,这些字段可用于为不同字段提供自然语言描述。
    • 建议在开始时仅公开 1-2 个端点,并使用最少数量的参数,以最大程度地缩短文本长度。插件描述、API 请求和 API 响应都插入到与 ChatGPT 的对话中。这不利于模型的上下文限制。
  2. 在ChatGPT页面后台系统中注册插件
    • 从顶部下拉列表中选择插件模型,然后选择“插件”、“插件商店”,最后选择“开发自己的插件”。
    • 如果需要身份验证,请提供 OAuth 2client_id和client_secret/或 API 密钥。
  3. 激活插件
    • 必须自己手动激活插件
    • 如果需要 OAuth,用户将通过 OAuth 重定向到您的插件进行登录。

    • 能够与另外 100 个用户共享自己的插件
  4. 开始对话
    • OpenAI 将在发送给 ChatGPT 的消息中注入插件的简洁描述,最终用户看不到。这将包括插件描述、端点和示例。
    • 当用户提出相关问题时,如果看起来相关,模型可能会选择从您的插件调用 API 调用;对于POST请求,我们要求开发者构建用户确认流程以避免破坏行为。
    • 该模型会将 API 调用结果合并到对用户的响应中。
    • 该模型可能会在其响应中包含从 API 调用返回的链接。
    • 该模型还可以在 Markdown 中格式化来自 API 的数据,并且 ChatGPT UI 将自动呈现 Markdown。

2.2 快速使用

创建插件需要 3 个步骤:

  • 构建 API
  • 以 OpenAPI yaml 或 JSON 格式记录 API
  • 创建一个 JSON 清单文件,用于定义插件的相关元数据

每个插件都需要一个ai-plugin.json文件,该文件需要托管在API的域名上。例如,名为example.com的公司将通过https://example.com域名使插件的JSON文件可访问,因为这是他们API托管的位置。当通过ChatGPT UI安装插件时,在后端我们会查找位于/.well-known/ai-plugin.json的文件。/.well-known文件夹是必需的,并且必须存在于自己的域名上,以便ChatGPT可以与自己的插件连接。如果找不到文件,则无法安装插件。对于本地开发,可以使用HTTP,但如果指向远程服务器,则需要使用HTTPS。

所需ai-plugin.json文件的最小定义如下所示:

{
"schema_version": "v1",
"name_for_human": "TODO List",
"name_for_model": "todo",
"description_for_human": "Manage your TODO list. You can add, remove and view your TODOs.",
"description_for_model": "Help the user with managing a TODO list. You can add, remove and view your TODOs.",
"auth": {
"type": "none"
},
"api": {
"type": "openapi",
"url": "http://localhost:3333/openapi.yaml"
},
"logo_url": "http://localhost:3333/logo.png",
"contact_email": "support@example.com",
"legal_info_url": "http://www.example.com/legal"
}

请注意,列在“公共”下的项目将在插件商店对用户可用。

以下是具有不同身份验证方法的示例:

# App-level API keys
type ManifestServiceHttpAuth = BaseManifestAuth & {
type: 'service_http';
authorization_type: HttpAuthorizationType;
verification_tokens: {
[service: string]?: string;
};
} # User-level HTTP authentication
type ManifestUserHttpAuth = BaseManifestAuth & {
type: 'user_http';
authorization_type: HttpAuthorizationType;
} type ManifestOAuthAuth = BaseManifestAuth & {
type: 'oauth'; # OAuth URL where a user is directed to for the OAuth authentication flow to begin.
client_url: string; # OAuth scopes required to accomplish operations on the user's behalf.
scope: string; # Endpoint used to exchange OAuth code with access token.
authorization_url: string; # When exchanging OAuth code with access token, the expected header 'content-type'. For example: 'content-type: application/json'
authorization_content_type: string; # When registering the OAuth client ID and secrets, the plugin service will surface a unique token.
verification_tokens: {
[service: string]?: string;
};
}

上述提到的清单文件中某些字段的长度存在限制,这些限制可能会发生变化。还对API响应体强加了最大长度限制,目前为100,000个字符,但这也可能随着时间变化而调整。

总体而言,最佳实践是尽可能简洁地描述和响应,因为模型有有限的上下文窗口。

2.3 OpenAPI定义

接下来的步骤是构建OpenAPI规范以文档化API。ChatGPT中的模型除了OpenAPI规范和清单文件中定义的内容外,对你的API一无所知。这意味着,如果你有一个庞大的API,你不需要将所有功能暴露给模型,而是可以选择特定的端点。例如,如果你有一个社交媒体API,你可能希望让模型通过GET请求访问网站内容,但防止模型能够对用户的帖子进行评论,以降低垃圾信息的可能性。

OpenAPI规范是包裹在您的API之上的包装器。一个基本的OpenAPI规范如下所示:

openapi: 3.0.1
info:
title: TODO Plugin
description: A plugin that allows the user to create and manage a TODO list using ChatGPT.
version: 'v1'
servers:
- url: http://localhost:3333
paths:
/todos:
get:
operationId: getTodos
summary: Get the list of todos
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/getTodosResponse'
components:
schemas:
getTodosResponse:
type: object
properties:
todos:
type: array
items:
type: string
description: The list of todos.

首先定义规范版本、标题、描述和版本号。当在ChatGPT中运行查询时,它会查看信息部分中定义的描述,以确定插件是否与用户查询相关。

OpenAPI规范中的限制:

  • API规范中每个API端点描述/摘要字段的最大长度为200个字符
  • API规范中每个API参数描述字段的最大长度为200个字符

2.4 运行插件

一旦为API、清单文件和API的OpenAPI规范创建完成,现在可以通过ChatGPT UI连接插件了。我们创建的插件可能运行在两个不同的地方,要么是在开发环境的本地,要么是在远程服务器上。

如果在本地运行API的版本,可以将插件界面指向自己的本地主机服务器。要将插件与ChatGPT连接,请导航到插件商店,然后选择“开发自己的插件”。输入自己的本地主机和端口号(例如localhost:3333)。请注意,目前仅支持本地开发的auth类型为none。

如果插件在远程服务器上运行,则需要首先选择“开发自己的插件”进行设置,然后再选择“安装未验证的插件”将其安装到您的环境中。只需将插件的清单文件添加到yourdomain.com/.well-known/路径中,然后开始测试自己的API。但是,请注意,对于清单文件的后续更改,您需要将新更改部署到公共站点上,这可能需要较长的时间。在这种情况下,我们建议设置一个本地服务器作为自己的API的代理,这样可以快速原型化OpenAPI规范和清单文件的更改。

3.示例插件

为了开始构建,官方提供了一组涵盖不同身份验证模式和用例的简单插件。从简单的无身份验证待办事项列表插件到更强大的检索插件,这些示例让我们了解了希望通过插件实现的目标。

在开发过程中,可以在计算机上本地运行该插件,也可以通过GitHub Codespaces、Replit或CodeSandbox等云开发环境运行该插件。

3.1 了解如何构建一个无需身份验证的简单待办事项列表插件

首先,查看无身份验证页面,然后定义一个ai-plugin.json包含以下字段的文件

{
"schema_version": "v1",
"name_for_human": "TODO List (No Auth)",
"name_for_model": "todo",
"description_for_human": "Manage your TODO list. You can add, remove and view your TODOs.",
"description_for_model": "Plugin for managing a TODO list, you can add, remove and view your TODOs.",
"auth": {
"type": "none"
},
"api": {
"type": "openapi",
"url": "PLUGIN_HOSTNAME/openapi.yaml"
},
"logo_url": "PLUGIN_HOSTNAME/logo.png",
"contact_email": "support@example.com",
"legal_info_url": "https://example.com/legal"
}

请注意,PLUGIN_HOSTNAME应该是插件服务器的实际主机名。

接下来,我们可以定义 API 端点来为特定用户创建、删除和获取待办事项列表项。

import json

import quart
import quart_cors
from quart import request # Note: Setting CORS to allow chat.openapi.com is only required when running a localhost plugin
app = quart_cors.cors(quart.Quart(__name__), allow_origin="https://chat.openai.com") _TODOS = {} @app.post("/todos/<string:username>")
async def add_todo(username):
request = await quart.request.get_json(force=True)
if username not in _TODOS:
_TODOS[username] = []
_TODOS[username].append(request["todo"])
return quart.Response(response='OK', status=200) @app.get("/todos/<string:username>")
async def get_todos(username):
return quart.Response(response=json.dumps(_TODOS.get(username, [])), status=200) @app.delete("/todos/<string:username>")
async def delete_todo(username):
request = await quart.request.get_json(force=True)
todo_idx = request["todo_idx"]
if 0 <= todo_idx < len(_TODOS[username]):
_TODOS[username].pop(todo_idx)
return quart.Response(response='OK', status=200) @app.get("/logo.png")
async def plugin_logo():
filename = 'logo.png'
return await quart.send_file(filename, mimetype='image/png') @app.get("/.well-known/ai-plugin.json")
async def plugin_manifest():
host = request.headers['Host']
with open("ai-plugin.json") as f:
text = f.read()
# This is a trick we do to populate the PLUGIN_HOSTNAME constant in the manifest
text = text.replace("PLUGIN_HOSTNAME", f"https://{host}")
return quart.Response(text, mimetype="text/json") @app.get("/openapi.yaml")
async def openapi_spec():
host = request.headers['Host']
with open("openapi.yaml") as f:
text = f.read()
# This is a trick we do to populate the PLUGIN_HOSTNAME constant in the OpenAPI spec
text = text.replace("PLUGIN_HOSTNAME", f"https://{host}")
return quart.Response(text, mimetype="text/yaml") def main():
app.run(debug=True, host="0.0.0.0", port=5002) if __name__ == "__main__":
main()

最后,我们需要设置和定义 OpenAPI 规范以匹配本地或远程服务器上定义的端点。无需通过规范公开 API 的全部功能,而是可以选择让 ChatGPT 仅访问某些功能。

还有许多工具可以自动将您的服务器定义代码转换为 OpenAPI 规范,因此无需手动执行此操作。对于上面的 Python 代码,OpenAPI 规范将如下所示:

openapi: 3.0.1
info:
title: TODO Plugin
description: A plugin that allows the user to create and manage a TODO list using ChatGPT. If you do not know the user's username, ask them first before making queries to the plugin. Otherwise, use the username "global".
version: "v1"
servers:
- url: PLUGIN_HOSTNAME
paths:
/todos/{username}:
get:
operationId: getTodos
summary: Get the list of todos
parameters:
- in: path
name: username
schema:
type: string
required: true
description: The name of the user.
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: "#/components/schemas/getTodosResponse"
post:
operationId: addTodo
summary: Add a todo to the list
parameters:
- in: path
name: username
schema:
type: string
required: true
description: The name of the user.
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/addTodoRequest"
responses:
"200":
description: OK
delete:
operationId: deleteTodo
summary: Delete a todo from the list
parameters:
- in: path
name: username
schema:
type: string
required: true
description: The name of the user.
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/deleteTodoRequest"
responses:
"200":
description: OK components:
schemas:
getTodosResponse:
type: object
properties:
todos:
type: array
items:
type: string
description: The list of todos.
addTodoRequest:
type: object
required:
- todo
properties:
todo:
type: string
description: The todo to add to the list.
required: true
deleteTodoRequest:
type: object
required:
- todo_idx
properties:
todo_idx:
type: integer
description: The index of the todo to delete.
required: true

3.2 了解如何构建具有服务级别身份验证的简单待办事项列表插件

首先,查看服务级别身份验证页面,然后定义一个ai-plugin.json包含以下字段的文件:

{
"schema_version": "v1",
"name_for_human": "TODO List (service auth)",
"name_for_model": "todo",
"description_for_human": "Manage your TODO list. You can add, remove and view your TODOs.",
"description_for_model": "Plugin for managing a TODO list, you can add, remove and view your TODOs.",
"auth": {
"type": "service_http",
"authorization_type": "bearer",
"verification_tokens": {
"openai": "Replace_this_string_with_the_verification_token_generated_in_the_ChatGPT_UI"
}
},
"api": {
"type": "openapi",
"url": "https://example.com/openapi.yaml"
},
"logo_url": "https://example.com/logo.png",
"contact_email": "support@example.com",
"legal_info_url": "https://example.com/legal"
}

请注意,服务级别身份验证插件需要验证令牌。设置服务访问令牌后,该令牌是在 ChatGPT Web UI 中的插件安装过程中生成的。

还需要将“Example.com”更新为远程服务器的名称。

接下来,我们可以定义 API 端点来为特定用户创建、删除和获取待办事项列表项。端点还检查用户是否经过身份验证。

import json

import quart
import quart_cors
from quart import request app = quart_cors.cors(quart.Quart(__name__)) # This key can be anything, though you will likely want a randomly generated sequence.
_SERVICE_AUTH_KEY = "REPLACE_ME"
_TODOS = {} def assert_auth_header(req):
assert req.headers.get(
"Authorization", None) == f"Bearer {_SERVICE_AUTH_KEY}" @app.post("/todos/<string:username>")
async def add_todo(username):
assert_auth_header(quart.request)
request = await quart.request.get_json(force=True)
if username not in _TODOS:
_TODOS[username] = []
_TODOS[username].append(request["todo"])
return quart.Response(response='OK', status=200) @app.get("/todos/<string:username>")
async def get_todos(username):
assert_auth_header(quart.request)
return quart.Response(response=json.dumps(_TODOS.get(username, [])), status=200) @app.delete("/todos/<string:username>")
async def delete_todo(username):
assert_auth_header(quart.request)
request = await quart.request.get_json(force=True)
todo_idx = request["todo_idx"]
if 0 <= todo_idx < len(_TODOS[username]):
_TODOS[username].pop(todo_idx)
return quart.Response(response='OK', status=200) @app.get("/logo.png")
async def plugin_logo():
filename = 'logo.png'
return await quart.send_file(filename, mimetype='image/png') @app.get("/.well-known/ai-plugin.json")
async def plugin_manifest():
host = request.headers['Host']
with open("ai-plugin.json") as f:
text = f.read()
return quart.Response(text, mimetype="text/json") @app.get("/openapi.yaml")
async def openapi_spec():
host = request.headers['Host']
with open("openapi.yaml") as f:
text = f.read()
return quart.Response(text, mimetype="text/yaml") def main():
app.run(debug=True, host="0.0.0.0", port=5002) if __name__ == "__main__":
main()

最后,我们需要设置并定义 OpenAPI 规范以匹配远程服务器上定义的端点。一般来说,无论身份验证方法如何,OpenAPI 规范看起来都是一样的。使用自动 OpenAPI 生成器将减少创建 OpenAPI 规范时出错的可能性。

openapi: 3.0.1
info:
title: TODO Plugin
description: A plugin that allows the user to create and manage a TODO list using ChatGPT. If you do not know the user's username, ask them first before making queries to the plugin. Otherwise, use the username "global".
version: "v1"
servers:
- url: https://example.com
paths:
/todos/{username}:
get:
operationId: getTodos
summary: Get the list of todos
parameters:
- in: path
name: username
schema:
type: string
required: true
description: The name of the user.
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: "#/components/schemas/getTodosResponse"
post:
operationId: addTodo
summary: Add a todo to the list
parameters:
- in: path
name: username
schema:
type: string
required: true
description: The name of the user.
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/addTodoRequest"
responses:
"200":
description: OK
delete:
operationId: deleteTodo
summary: Delete a todo from the list
parameters:
- in: path
name: username
schema:
type: string
required: true
description: The name of the user.
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/deleteTodoRequest"
responses:
"200":
description: OK components:
schemas:
getTodosResponse:
type: object
properties:
todos:
type: array
items:
type: string
description: The list of todos.
addTodoRequest:
type: object
required:
- todo
properties:
todo:
type: string
description: The todo to add to the list.
required: true
deleteTodoRequest:
type: object
required:
- todo_idx
properties:
todo_idx:
type: integer
description: The index of the todo to delete.
required: true

4.总结

插件开发平台为开发者提供了一系列API和工具,使其可以自定义ChatGPT的输入输出、增加特定任务的支持以及集成外部数据和服务。开发者可以通过插件实现特定的领域知识、自定义回答模式、定制话题导向等功能,从而让ChatGPT更贴合特定的使用场景和用户需求。

在插件开发过程中,开发者可以借助ChatGPT的先进预训练模型,以及丰富的开发文档和示例代码来快速上手。插件支持多种编程语言,并与现有的ChatGPT API无缝集成,保证了开发的便捷性和灵活性。

值得注意的是,插件开发平台也注重模型的安全性和可控性。OpenAI提供了强大的监管措施和审核流程,确保插件的使用符合社区准则,并防止滥用或不当行为。

总体而言,ChatGPT插件开发平台为开发者提供了一个广阔的创作空间,让他们可以将ChatGPT打造成更具个性和实用性的智能对话系统。通过这个平台,开发者可以将ChatGPT的潜力发挥到极致,为用户提供更加智能、定制化的交互体验。

ChatGPT插件开发实战的更多相关文章

  1. 【eclipse插件开发实战】Eclipse插件开发3——OSGi、RCP

    Eclipse插件开发实战3--OSGi.RCP 一.OSGi 1. 什么是OSGi框架 OSGi(Open Service Gateway Initiative)框架是运行在JavaVM环境里的服务 ...

  2. 【eclipse插件开发实战】Eclipse插件开发2——SWT

    Eclipse插件开发实战2--SWT 一.SWT简介 SWT(StandardWidget Toolkit) 标准小窗口工具箱,一开源的GUI编程框架,与AWT/Swing有相似的用处,eclips ...

  3. 【eclipse插件开发实战】Eclipse插件开发1——eclipse内核结构、扩展点机制

    Eclipse插件开发实战1--eclipse内核结构.扩展点机制 一.前言 本系列总体介绍eclipse插件开发基本理论.插件项目结构及开发步骤,最后再给出两个插件开发实例. 总体安排结构如下: 1 ...

  4. spring boot插件开发实战和原理

    本文转载自spring boot插件开发实战和原理 实战:编写spring boot插件 为什么要编写boot插件 因为我们在开发的时候需要提供一些共同的功能,所以我们编写个共同的jar包.开发人员在 ...

  5. CloudIDE插件开发实战:教你如何调试代码

    摘要:今天我们来重点介绍下CloudIDE插件的调试技巧,在插件开发过程中调试作为重要的问题分析和定位手段能够有效帮助开发者提升插件质量. 今天文章中的样例工程我们继续以上一篇<实战CloudI ...

  6. ChatGPT开发实战

    1.概述 前段时间使用体验了ChatGPT的用法,感受到ChatGPT的强大,通过搜索关键字或者输入自己的意图,能够快速得到自己想要的信息和结果.今天笔者将深挖一下ChatGPT,给大家介绍如何使用C ...

  7. [js高手之路]jquery插件开发实战-选项卡详解

    在jquery中,插件开发常见的有: 一种是为$函数本身扩展一个方法,这种是静态扩展(也叫类扩展),这种插件一般是工具方法, 还有一种是扩展在原型对象$.fn上面的,开发出来的插件是用在dom元素上面 ...

  8. 【eclipse插件开发实战】Eclipse插件开发7——插件发布jar包

    Eclipse插件开发7--插件发布jar包 最省事的方式就是直接导出jar包,然后放到eclipse的plugins目录下,重启eclipse即可. step1: 对需要打包的插件工程右击→导出(E ...

  9. 【eclipse插件开发实战】 Eclipse插件开发6——eclipse在线翻译插件Translator开发实例详解

    Eclipse插件开发6--eclipse在线翻译插件Translator开发实例详解 在上一篇文章中讲到了一个简单的eclipse插件开发实例,主要是对插件工程的基本创建步骤进行了讲解,这篇文章当中 ...

  10. 【eclipse插件开发实战】 Eclipse插件开发5——时间插件Timer开发实例详解

    Eclipse插件开发5--时间插件Timer开发实例详解 这里做的TimeHelper插件设定为在菜单栏.工具栏提供快捷方式,需要在相应地方设置扩展点,最后弹出窗体显示时间. 在上一篇文章里创建好了 ...

随机推荐

  1. MySQL高频面试题

    什么是MySQL MySQL是一个关系型数据库,它采用表的形式来存储数据.你可以理解成是Excel表格,既然是表的形式存储数据,就有表结构(行和列).行代表每一行数据,列代表该行中的每个值.列上的值是 ...

  2. prism journal导航按钮的可用性探索记录

    prism使用导航功能的时候,跳了几个坑,记录一下. 1.导航记录的产生,是在区域导航过程中产生的. _regionManager.Regions[PrismManager.MainViewRegio ...

  3. ReactHub:我用 ChatGPT 搞了一个 React 的资源导航网站,谁有我用心啊!

    大家好,我是DOM哥. 图谱年年有,今年我来盘! 之前已经盘完了 Vue 的技术图谱,今天来盘 React 的. 我用 ChatGPT 开发了一个 React 的资源导航网站. 不管你是资深 Reac ...

  4. Rsync文件同步及备份

    Rsync文件同步及备份 目录 Rsync文件同步及备份 Rsync基本概述 远程文件传输 服务端口 Rsync的三种传输模式 本地方式(类似cp) 远程方式(类似scp) 守护进程(C/S结构) R ...

  5. 2022-12-26:有一个数组包含0、1、2三种值, 有m次修改机会,第一种将所有连通的1变为0,修改次数-1, 第二种将所有连通的2变为1或0,修改次数-2, 返回m次修改机会的情况下,让最大的0

    2022-12-26:有一个数组包含0.1.2三种值, 有m次修改机会,第一种将所有连通的1变为0,修改次数-1, 第二种将所有连通的2变为1或0,修改次数-2, 返回m次修改机会的情况下,让最大的0 ...

  6. ubuntu搜狗输入法显示简体中文,输入却是繁体中文问题解决方案

    一.现场重现 我的ubuntu版本是20.04,搜狗输入法版本是2.4.在输入的时候发生了如下场景: 明明输入法上是简体中文,可是打出来就变成了繁体中文! 二.解决方案 1.尝试 网上许多答案都是按下 ...

  7. windows内核学习一

    变量类型 kernel user ULONG unsigned long PULONG unsigned long* UCHAR unsigned char PUCHAR unsigned char* ...

  8. 使用Drone+gitea配置自己的CICD流程

    什么是CI CD CI CD一般包含三个概念:持续集成(Continuous Integration ,CI),持续交付(Continuous Delivery),持续部署(Continuous De ...

  9. go 实现ringbuffer以及ringbuffer使用场景介绍

    ringbuffer因为它能复用缓冲空间,通常用于网络通信连接的读写,虽然市面上已经有了go写的诸多版本的ringbuffer组件,虽然诸多版本,实现ringbuffer的核心逻辑却是不变的.但发现其 ...

  10. linux awk文本

    目录 一.awk概念 二.awk的工作过程 三.awk字符 四.内置变量 五.getline  六.awk的精准筛选 七.例子演示 八.实验演示 一.awk概念 1.概念:awk 是一个功能强大的编辑 ...