Linux: 命令行参数和环境变量究竟是什么?

Linux: 命令行参数和环境变量究竟是什么?

  • 一、命令行参数
    • 1.1 main函数参数意义
    • 1.2 命令行参数概念
    • 1.3 命令行参数实例
  • 二、环境变量
    • 2.1 环境变量概念
    • 2.2 环境变量:PATH
      • 2.2.1 如何查看PATH中的内容
      • 2.2.2 如何让自己的可执行文件不带路径运行
    • 2.3 环境变量:PWD
    • 2.3 环境变量: HOME
  • 三、获取环境变量的3种方式
    • 3.1 getenv()函数
    • 3.2 main函数传参
    • 3.3 通过第三方变量environ获取(extern char** environ)
  • 四、环境变量如何获取
    • 4.1 子进程环境变量获取方式
    • 4.2 父进程环境变量获取方式
  • 五、本地变量和环境变量
  • 六、Linux命令分类和环境变量相关的命令

一、命令行参数

 在main函数中,我们可以给main函数传递3个参数(库函数头为main(int argc, char *argv[], char *env[]))(这里我们只用前两个参数)。那究竟如何给main函数传递参数呢?每个参数分别表示什么?

1.1 main函数参数意义

main函数中,argc表示指针数组arvg中有效元素的个数。接下来我们来看一段代码!

#include <stdio.h>
#include <string.h>
#include <stdlib.h>int main(int argc, char* argv[])                                                                                                                     
{                                                                  int i = 0;                                                     for(; i < argc; i++)                                           {                                                              printf("%d: %s\n", i, argv[i]);                            }                                                              
}   

【运行现象】:
在这里插入图片描述

1.2 命令行参数概念

 1.1中main()函数在运行时,我们输入的指令会被bash或shell当成一个大的字符串,并以空格的形式分割成若干个小的字符串。而这些小字符串会形成一张指针数组表,bash或shell会指针数组有效个数传给argc参数,指针数组表地址传给argc参数

在这里插入图片描述
 我们在来看看系统指令现象,来对比上述mian函数。

在这里插入图片描述

我们将上述这种lsls -lls -l -a称之为命令行参数。输入的指令会被bash或shell以空格分割成小字符串,并形成一种指针数组表用于存放每一个小的字符串,并将该指针数组的有效个数传递给mian函数的argc参数,而指针数组表的地址传递给argv参数。其中./mybinls这种为可执行程序、其他的为选项。命令行参数可以让同一段代码通过不同的选项来实现不同的功能!!

1.3 命令行参数实例

 下面我们希望一段代码,通过不同的指令来实现简单的计算器。其中格式为可执行程序 功能参数(add、sub、mul、div) 两个参与运算的数据d1 d2
 显然我们需要给mian函数中,有效字符的个数为4,此时我们仅需比较argv[1]传递的字符串是什么即可判断对于的功能选项。下面我们来看看如何实现吧!

#include <stdio.h>
#include <string.h>
#include <stdlib.h>int main(int argc, char *argv[])    
{    if(argc != 4)//传入数据错误,显示正确使用手册    {        printf("Use error\nUsage %s op[-add|sub|mul|div] d1 d2\n", argv[0]);    return 1;    }    int x = atoi(argv[2]);//将字符窜转整型    int y = atoi(argv[3]);    if(strcmp(argv[1], "add")==0)    {    int result = x + y;    printf("%d + %d = %d\n", x, y, result);    }    else if(strcmp(argv[1], "sub")==0)    {    int result = x - y;    printf("%d - %d = %d\n", x, y, result);    }    else if(strcmp(argv[1], "mul")==0)    {    int result = x * y;    printf("%d * %d = %d\n", x, y, result);                                                                                                          }    else if(strcmp(argv[1], "div")==0)    {    if(y == 0)//非法数据、除数为0{printf("%d/%d=error! div zero\n", x, y);}else {int result = x / y;printf("%d / %d = %d\n", x, y, result);}}else{printf("Use error\nUsage %s op[-add|sub|mun|div] d1 d2\n", argv[0]);}return 0;
}

【测试结果】:

在这里插入图片描述

二、环境变量

 在shell中,对于系统指令(lspwd)的我们直接在命令行输入相关指令便可执行对于的功能;但对于用于自己编写的可执行程序,运行时必须在前加./来指令程序的相对路径。而这种差异就和环境变量有关!!

2.1 环境变量概念

环境变量(environment variables)一般是指在操作系统中,用于指定操作系统运行环境的一些参数。环境变量通常具有特殊用途,并且具有全局特性!!
 比如我们在编写C/C++程序时,我们不知道、也不关心所谓的动/静态库在哪里。但我们每次都能编译成功,形成可执行程序。原因在于有相关的环境变量帮助编译器进行查找!!

下面我们来看看操作系统中,究竟有哪些常见的环境变量!

2.2 环境变量:PATH

PATH是用于指定系统搜索路径的环境变量。

 在命令行参数讲解中,有一个小细节。系统指令可以直接只需在命令行输入相关指令便可执行对于的功能,而我们自己的可执行程序必须在前面加./,否则会报错:command not found。这是为啥呢?
 原因在于运行一个可执行程序前,操作系统需要得到该可执行程序的路径
。这只是为啥我们自己的可执行程序必须加./才能运行。至于系统指令,原因在于环境变量PATH中保存着一系列系统搜索路径。运行系统指令时,操作系统会依次搜索PATH中保存的路径,只要PATH中保存了当前指令的存在路径,程序便可以运行成功!!

2.2.1 如何查看PATH中的内容

 我们可以通过指令echo $PATH来查看PATH中保存的内容。PATH保存的路径会以冒号作为分割符,将路径分隔开!

在这里插入图片描述

2.2.2 如何让自己的可执行文件不带路径运行

$emsp;让自己的可执行程序不带路径运行通常由两种方法:将可执行文件路径添加到PATH环境变量中、将可执行文件拷贝到系统的指定路径下!!

【将可执行文件路径添加到PATH环境变量】:
 我们可以通过指令PATH=&PATH:可执行文件路径将可执行文件路径添加到PATH环境变量!!

在这里插入图片描述

  • 上述行为都是对内存中的数据进行操作。默认更改的环境变量、仅限于本次登录!!

【将可执行文件拷贝到系统的指定路径下】:

在这里插入图片描述
tips:

  • 上述将指定文件拷贝到系统指定路径下的行为也被称为程序安装!!系统运行可执行程序时,默认会在环境变量和系统指令路径下进行查找!

2.3 环境变量:PWD

$emsp;我们在来看看下面这些指令:
在这里插入图片描述
 我们发现pwd指令每次都能成功获取到当前工作坐在路径!这时为何?
原因在于系统中存在一个环境变量PWD,该环境变量用于保存用户的当前工作路径。每次执行pwd执行时,pwd会读取环境变量PWD中的内容,并回显给用户!

2.3 环境变量: HOME

 我们每次在登录shell时,为什么对于root账号,所处工作目录为/root;而对于普通用户,则是/home xxx?
原因在于系统中存在某些环境变量,在我们还未登录时就已经被加载了。这些变量是由操作系统的配置文件或命令行参数指定的。当用于登录shell时,该环境变量会识别出用户的身份,从而初始化环境变量HOME。最后shell直接通过cd $HIME达到上述现象。
shell环境变量加载流程
在这里插入图片描述

三、获取环境变量的3种方式

 在Linux中,我们可以通过env指令来查看当前进程中的所有环境变量。而获取环境变量通常有以下3种方式。

3.1 getenv()函数

 在Linux中,提供一个名为getenv函数(char *getenv(const char *name););该函数可以获取环境变量中的内容。

例如:
【源代码】:

int main(int argc, char *argv[], char *env[])    
{    printf("PATH:%s\n", getenv("PATH"));; return 0;
}

【运行结果】:
在这里插入图片描述

3.2 main函数传参

 在命令行参数中,我们已经提到过mian函数可以传3个参数,mian函数原型为:main(int argc, char *argv[], char *env[])
程序在启动时,系统可以选择的给进程(main函数)提供两张表:命令行参数表(argc维护)、环境变量表(env维护)。

【源代码】:

#include <stdio.h>int main(int argc, char *argv[], char* env[])
{for(int i = 0; env[i]; i++)printf("env[%d]: %s\n", i, env[i]);return 0;
}

【运行结果】:
在这里插入图片描述

3.3 通过第三方变量environ获取(extern char** environ)

 在shell中,环境变量会以写时拷贝的方式继承给子进程。换而言之,环境变量具有全局属性,父子进程以写时拷贝的方式看到同一种环境变量表。
 那子进程如何“继承”的环境变量表呢?
libc中定义的全局变量environ指向环境变量表,environ没有包含在任何头文件中,所以在使用时 要用extern声明。

实例:
【源代码】:

#include <stdio.h>int main()
{extern char **environ;for(int i = 0; environ[i]; i++)printf("environ[%d]: %s\n", i, environ[i]);return 0;
}

【运行结果】:
在这里插入图片描述

四、环境变量如何获取

4.1 子进程环境变量获取方式

 命令行启动的进程都是shell或bash的子进程,而子进程的环境变量都是父进程以命令行参数的形式传递给子进程的。

4.2 父进程环境变量获取方式

 在shell中直接修改环境变量PATH虽然可行,但这是直接更改shell进程内部的环境变量信息。在下一次登录时,该修改值会被恢复!!

 这是由于父进程(准确的来说是shell)每次重新登录时,都会形成新的bash解释器,并且bash解释器会自动读取配置文件./.bash_profile(在家目录下)中的信息,为shell进程形成一张环境变量表!!即父进程shell的环境变量信息是以脚本配置文件的形式存在的!!

五、本地变量和环境变量

 在shell中除了系统默认的环境变量,也可以手动添加环境变量!

【例如】:

MYENV=helloLinux

在这里插入图片描述
 当上述添加的环境变量并未添加到环境变量表中,被称为本地变量。使用export指令可以将本地变量导入环境变量表中,变为环境变量!!即export MYENV

 本地变量只在bash进程内部有效,不会被子进程所继承;而环境变量通过让所有子进程继承的方式,实现全局性!

六、Linux命令分类和环境变量相关的命令

 在Linux中,Linux命令分为常规命令和内建命令。

命令种类用途
常规命令fork让子进程执行的。具体表现在对环境变量PATH清空后,诸如ls、cd、mkdir、touch等指令失效
内建命令shell内部的一个函数,可以直接读取shell内部的本地变量。如export、pwd

环境变量相关的命令

命令种类用途
echo显示某个环境变量值
export设置一个新的环境变量
env显示所有环境变量
unset清除环境变量
set:显示本地变量和环境变量

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/41195.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Android车载开发中调试app与bat结合的丝滑小妙招

项目场景&#xff1a; 做Android车载的小伙伴调试app的时候常年就是手动adb命令三连&#xff0c;例如我常用的adb推送apk的命令 adb root adb remount adb push D:\workspace_atc\XSP3-10A\AutoSystemUIPlugin\app\release\CarSystemUI.apk /system/priv-app/CarSystemUI …

kylin arm xcb版本异常问题解决

源码编译qt 未生成xcb库&#xff0c;查看源码xcb readme.txt 提示 版本要求 下载 [ANNOUNCE] libxcb 1.14 [ANNOUNCE] xcb-proto 1.14 解压源码编译, 先编译xcb-proto sudo ./configure --prefix/usr/local/xcb-proto make make install 在编译xcb export PKG_CONFIG_PATH…

并发编程(多线程)带来了哪些问题?

前面我们了解到多线程技术有很多好处,比如说多线程可以充分利用多核 CPU 的计算能力,那多线程难道就没有一点缺点吗? 有。 多线程很难掌握,稍不注意,就容易使程序崩溃。我们以在路上开车为例: 在一个单向行驶的道路上,每辆汽车都遵守交通规则,这时候整体通行是正常的…

C++基石:掌握高效编程的艺术

C 关于命名空间&#xff1a;namespace 上述文档详细介绍了C标准库&#xff08;Standard C Library&#xff09;的一些关键约定&#xff0c;这些约定不仅帮助开发者理解如何正确使用库中的功能&#xff0c;也明确了实现者在设计库时的灵活性和限制。下面是对文档中提到的几个要点…

部署LVS+keepalived做网站的高可用,高负载。

LVSkeepalived keepalived背景 针对LVS的辅助工具&#xff0c;主要提供故障切换与健康检查。 工作场景&#xff1a;作为调度器的双机热备&#xff0c;以及节点服务器的健康检查以及故障切换&#xff08;删除条目&#xff09;。 借鉴了VRRP协议来实现高可用。 keepalived部署…

后端学习(一)

添加数据库包&#xff1a; 数据库连接时 发生错误&#xff1a; 解决方式&#xff1a; SqlConnection conn new SqlConnection("serverlocalhost;databaseMyBBSDb;uidsa;pwd123456;Encryptfalse;") ;conn.Open();SqlCommand cmd new SqlCommand("SELECT * FROM…

WAIC上官宣!大模型语料提取工具MinerU正式发布,开源免费“敲”好用

7月4日&#xff0c;2024 WAIC科学前沿全体会议在上海世博中心红厅隆重举行。上海人工智能实验室与商汤科技联合香港中文大学和复旦大学正式发布新一代大语言模型书⽣浦语2.5&#xff08;InternLM2.5&#xff09;&#xff0c;同时全链条工具体系迎来重磅升级&#xff0c;对于大模…

Android 四大组件

1. Activity 应用程序中&#xff0c;一个Activity通常是一个单独的屏幕&#xff0c;它上面可以显示一些控件&#xff0c;也可以监听并对用户的事件做出响应。 Activity之间通过Intent进行通信&#xff0c;在Intent 的描述结构中&#xff0c;有两个最重要的部分&#xff1a;动…

Java跳出循环的四种方式

1、continue,break,return continue&#xff1a;跳出当前层循环的当前语句&#xff0c;执行当前层循环的下一条语句。   continue标签 break&#xff1a;跳出当前层循环。 break标签&#xff1a;多层循环时&#xff0c;跳到具体某层循环。 return&#xff1a;结束所有循环…

基于python 的动态虚拟主机

将自己电脑上的Python脚本文件上传到虚拟机/var/www/cgi-bin/目录下 [rootlocalhost conf.d]# cd /var/www/cgi-bin/ [rootlocalhost cgi-bin]# rz -E rz waiting to receive.编辑vhost.conf配置文件 [rootlocalhost conf.d]# vim vhost.conf<virtualhost 192.168.209.140…

树形结构C语言的实现

一.什么是树&#xff1a; 树形结构是一层次的嵌套结构。一个树形结构的外层和内层有相似的结构&#xff0c;所以这种结构多可以递归的表示。经典数据结构中的各种树状图是一种典型的树形结构&#xff1a;一棵树可以简单的表示为根&#xff0c;左子树&#xff0c;右子树。左子树…

平替向日葵:Windows远程桌面+动态IP获取器

对于需要远程办公的人员来说&#xff0c;向日葵是一个操作简便的选择&#xff0c;但其免费版功能受限&#xff0c;且由于数据需经过向日葵服务器转发&#xff0c;安全性也无法得到完全保障。为此&#xff0c;以下提供一个更为简单且免费的替代方案&#xff1a; 使用Windows自带…

threejs 微信小程序原生版本的使用 obj模型的加载

直接上代码&#xff0c; <canvas class"webgl" type"webgl" id"gl" bindtouchstart"onTX" bindtouchend"onTX" bindtouchmove"onTX" style"width:100vw;height:90vh"></canvas> const co…

从0到1构建渠道运营体系:实战案例与策略指南

引言 在当今竞争激烈的市场环境中&#xff0c;有效的渠道运营是企业实现产品或服务快速触达目标用户、提升市场份额的关键。从零开始构建一个高效的渠道运营体系&#xff0c;不仅需要深思熟虑的策略规划&#xff0c;还需要灵活应变的实战操作。本文将结合实战案例&#xff0c;…

react native中使用@react-navigation/native进行自定义头部

react native中使用react-navigation/native进行自定义头部 效果示例图实例代码 效果示例图 实例代码 /* eslint-disable react-native/no-inline-styles */ /* eslint-disable react/no-unstable-nested-components */ import React, { useLayoutEffect } from react; import…

七、Linux二进制安装Redis集群

目录 七、Linux二进制安装Redis集群1 安装Redis所需依赖2 单机安装Redis&#xff08;7.2.4&#xff09;2.1 下载Redis2.2 安装Redis 3 分布式部署模式&#xff08;Redis Cluster&#xff09;3.1 分布式部署模式的配置文件3.2创建集群 4 主从复制模式&#xff08;Redis Sentinel…

鼠标自动点击器怎么用?鼠标连点器入门教程!

鼠标自动点击器是适用于Windows电脑的自动执行鼠标点击操作的工具&#xff0c;主要用于模拟鼠标点击操作&#xff0c;实现鼠标高速点击的操作。通过模拟鼠标点击&#xff0c;可以在用户设定的位置、频率和次数下自动执行点击动作。 鼠标自动点击器主要的应用场景&#xff1a; …

Wing FTP Server

文章目录 1.Wing FTP Server简介1.1主要特点1.2使用教程 2.高级用法2.1Lua脚本,案例1 1.Wing FTP Server简介 Wing FTP Server&#xff0c;是一个专业的跨平台FTP服务器端&#xff0c;它拥有不错的速度、可靠性和一个友好的配置界面。它除了能提供FTP的基本服务功能以外&#…

当心!不要在SpringBoot中再犯这样严重的错误

1. 简介 在Spring Boot中&#xff0c;Configuration注解用于声明配置类&#xff0c;以定义和注册Bean对象。这些Bean对象可以是普通的业务组件&#xff0c;也可以是特殊的处理器&#xff0c;如BeanPostProcessor或BeanFactoryPostProcessor&#xff0c;用于在Spring容器中对其…

比 PIP 快 100 倍的安装工具

uv 是一个由 Rust 开发的 pip 工具&#xff0c;比 pip 快 100 倍&#xff0c;难以置信&#xff0c;不过真的是快太多了。 安装 在 Mac 上直接通过 brew install uv 安装即可。 venv 创建运行环境&#xff0c;默认当前目录下 .venv uv venv 依赖安装 uv pip install -r re…