零)用unset来撤销数组,可用unset array_name[i]来删除里面的元素:
declare -A DATABASES

# mail
DATABASES['10.70.62.5-3306']='postfix_mail'
用unset来撤销数组,可用unset array_name[i]来删除里面的元素
#cat  arrayunset.sh  

#sh  arrayunset.sh
echo bai manage postfix_mail



一)${#array_name[@]} 或者 ${#array_name[*]}都可以用来求数组的长度
#cat ping3times.sh  






#sh  arrayloop.sh
jerry
alice
david
wendy


二)${array_name[@]} 或者 ${array_name[*]} 都可以全部显示数组中的元素


#sh arraylist.sh
jerry
alice
david
wendy
jerry alice david wendy


来自:https://blog.csdn.net/Jerry_1126/article/details/52027539
对于写判断的语句,如for,需要放在花括号里头,{},否则会报错,这是AWK的语法:
cat sql.txt
http://adff.com 300,300,300
http://adff1.com 300,300,300
http://adff2.com 300,300,300
http://adff3.com 300,300,300
http://adff4.com 300,300,300,300,300

cat sql.txt |awk '{a=split($2,filearray,",")}{for (i=1;i<=a;i++) printf ("%s/v=%s\n",$1,i)}'
http://adff.com/v=1
http://adff.com/v=2
http://adff.com/v=3
http://adff1.com/v=1
http://adff1.com/v=2
http://adff1.com/v=3
http://adff2.com/v=1
http://adff2.com/v=2
http://adff2.com/v=3
http://adff3.com/v=1
http://adff3.com/v=2
http://adff3.com/v=3
http://adff4.com/v=1
http://adff4.com/v=2
http://adff4.com/v=3
http://adff4.com/v=4
http://adff4.com/v=5

之前加个end,发现只输出最后一行,不对。去了END就好了,end表示其后的语句在所有语句执行后才执行,做一些计算后的总结打印输出,BEGIN表示在所有语句执行前执行:

http://adff4.com/1
http://adff4.com/2
http://adff4.com/3
http://adff4.com/4
http://adff4.com/5
背影:对于低配置机器,建议写死PHP-FPM进程数得了,而对于高配置机器,则如果写在动态的,因为根据流量进行fork了PHP-FPM进程运动量很大,应该是在高配置身体健康的时候去做,等你是一个低配置的机器,你再去做增加进程去做时就死了。

一)PHP-FPM子进程数量应该如何设置?



二)php-fpm.conf 配置说明:
php-fpm中pm.start_servers 多大合适?
{(cpu空闲时等待连接的php的最小子进程数) + (cpu空闲时等待连接的php的最大子进程数 - cpu空闲时等待连接的php的最小子进程数)/ 2};
用配置表示就是:min_spare_servers + (max_spare_servers - min_spare_servers) / 2;一般而言,设置成10-20之间的数据足够满足需求了。
英文表示@/usr/local/php/etc/php-fpm.conf:
; The number of child processes created on startup.
; Note: Used only when pm is set to 'dynamic'
; Default Value: min_spare_servers + (max_spare_servers - min_spare_servers) / 2

1)XIYOU-API线上24G(24576M),24CPU生产机器配置:


2)目前RPMBUILD打包写死:
/home/test/rpmbuild/SOURCES/php-fpm.conf
/home/test/rpmbuild/SOURCES/www.conf


3)通过grep从/usr/local/php/etc/php-fpm.conf里陪陪出对应项的值:


附,php-fpm.conf 配置说明:


来自:https://blog.csdn.net/u013372487/article/details/80168979


HP-FPM子进程数量应该如何设置?摘录自:https://blog.csdn.net/jt521xlg/article/details/50992631 ,最前面参考计算最小PHP进程来源:
首先,我们关注下 PHP-FPM 的运行方式:

static :表示在 `php-fpm` 运行时直接 `fork` 出 `pm.max_chindren` 个子进程,

dynamic:表示,运行时 `fork` 出 `start_servers` 个进程,随着负载的情况,动态的调整,最多不超过 `max_children` 个进程。
一般推荐用 static。

优点是不用动态的判断负载情况,提升性能;

缺点是多占用些系统内存资源。

PHP-FPM 子进程数量,是不是越多越好?

当然不是,pm.max_chindren,进程多了,增加进程管理的开销以及上下文切换的开销。

更核心的是,能并发执行的 php-fpm 进程不会超过 cpu 个数。

如何设置,取决于你的代码

如果代码是 CPU 计算密集型的,pm.max_chindren 不能超过 CPU 的内核数。

如果不是,那么将 pm.max_chindren 的值大于 CPU 的内核数,是非常明智的。

国外技术大拿给出这么个公式:

在 N + 20% 和 M / m 之间。

N 是 CPU 内核数量。
M 是 PHP 能利用的内存数量。
m 是每个 PHP 进程平均使用的内存数量。

适用于 dynamic 方式。

static方式:M / (m * 1.2)

当然,还有一种保险的方式,来配置 max_children。适用于 static 方式。

先把 max_childnren 设置成一个比较大的值。
稳定运行一段时间后,观察 php-fpm 的 status 里的 max active processes 是多少
然后把 max_children 配置比它大一些就可以了。
pm.max_requests:指的是每个子进程在处理了多少个请求数量之后就重启。

这个参数,理论上可以随便设置,但是为了预防内存泄漏的风险,还是设置一个合理的数比较好

来自:https://blog.csdn.net/jt521xlg/article/details/50992631
基础知识:
对于斜杠来讲,在PHP里即使是单引号,它也是会和类似双引号里的$一样,有被转义:
'/\\\\/'
cat a.php

php a.php
\
cat reg3.php  


来自微信群:是因为双引号的原因,\#在双引号里,就是\#,\\#在双引号里,就是\#,\\\#在双引号里,就是\\#。

之前http://jackxiang.com/post/6466/研究过反斜杠,没有研究过$,这次主要研究$。
"^-? \\d+$":这个正则表达式为什么会有两个反斜杠
这要分两步看
首先字符串中的\\被编译器解释为\
然后作为正则表达式,\d又被正则表达式引擎解释为元字符只匹配数字
正则表达式中匹配一个反斜杠要用四个反斜杠,为什么呢?

分析一下“\\\\”,第一个斜杠是转义符,第二个斜杠是斜杠本身,第三个斜杠是转义符,第四个斜杠是斜杠本身。
有2点要清楚:
1.字符串里面表示斜杠就需要两个斜杠如“\\”
2.正则表达式里的斜杠需要转意,是用“\\”标示。
这样就比较好解释:
我们先要表示正则表达式里面的斜杠“\\”,然后再用字符串表示出来。而这2个斜杠分别需要一个转义符,这样就成了4个斜杠在正则表达式里面表示一个斜杠。
From:https://my.oschina.net/airship/blog/411045
阅读全文
背景:很常用的一些基础文本操作,记录下来备查。
一)把空格连接改为|连接:
#cat b
a b c d

awk -vOFS="|" 'NF+=0' b
a|b|c|d

[解析]
  替换字段分割符,必须要对字段有个action才能使OFS生效,这里我们运用 NF+=0 的方法,即有了操作,而并为改变其原有的值,很巧妙吧。

二)去空行:
cat a
1

2

3

awk NF a
1
2
3

[解析]
  排除空行,因为空行NF=0,0为假不会打印该行。

三)输出中间列:
#cat c
a b c d e f
1 2 3 4

awk 'NF-=2' c
a b c d
1 2

awk '{for(i=3;i<NF;i++)printf("%s ",$i);print $NF}' c
c d e f
3 4

$NF:最后一列

[解析]
  不输出后面2个字段和前面2个字段。

实践来自:https://blog.csdn.net/zwj1030711290/article/details/53923459





一)把空格连接改为|连接:
#cat b
a b c d

awk -vOFS="|" 'NF+=0' b
a|b|c|d


二)去空行:
cat a
1

2

3

awk NF a
1
2
3


三)
背景:个人博客里的友情链接发现好多链接都404了,要么是域名注册到期没有续费,要么搬家了,根本连接不过去了,影响页面加载速度怎么能快速清理掉?PHP版本的,只获取Header头,不获取Body内容的:http://jackxiang.com/post/6818/ ,尽管PHP比较能写,但是没有Shell更快实现作下简单一行处理。
一)Linux下的一句话脚本:

二)写成多行:

三)分割文件,子Shell处理,没实践,代码如下:
觉得数据多了就别直接用bash和curl做,换其他并发和网络编程更方便的语言。



来自:http://www.dewen.net.cn/q/15394/%E5%A6%82%E4%BD%95%E5%8A%A0%E5%BF%ABshell%E6%89%B9%E9%87%8F%E8%8E%B7%E5%8F%96url%E7%8A%B6%E6%80%81%E7%A0%81%E7%9A%84%E9%80%9F%E5%BA%A6%EF%BC%9F
https://jingyan.baidu.com/article/fdbd4277d59af8b89e3f4895.html

cat t3.yml


ls /tmp/test/
10  12  14  16  4  6  8

来自:http://54im.com/ansible-doc/playbooks_loops.html#looping-over-integer-sequences


批量创建目录:
哈喽,大家好,今天小编给大家带来一篇如何在使用scp命令式递归的排除文件,希望对大家有所帮助,raksmart服务器。

首先我需要将所有包含 *.c 文件的文件夹从名为 hostA 的本地笔记本复制到 hostB。我使用的是下面的 scp 命令,但不知道如何排除特定的文件(如 *.out):

$ scp-r ~/projects/ user@hostB:/home/delta/projects/

如何告诉 scp 命令在 Linux/Unix 命令行中排除特定的文件或目录?

人们可以使用 scp 命令在网络主机之间安全地复制文件。它使用 ssh 进行数据传输和身份验证。典型的语法是:

scp file1 user@host:/path/to/dest/

scp-r /path/to/source/ user@host:/path/to/dest/

scp 排除文件

我不认为你可以在使用 scp 命令时过滤或排除文件。但是,有一个很好的解决方法来排除文件并使用 ssh 安全地复制它。本页面说明如何在使用 scp 递归复制目录时过滤或排除文件。

如何使用 rsync 命令排除文件

语法是:

rsync av -e ssh--exclude='*.out'/path/to/source/ user@hostB:/path/to/dest/

这里:

-a :递归到目录,即复制所有文件和子目录。另外,打开归档模式和所有其他选项(相当于 -rlptgoD)

-v :详细输出

-e ssh :使用 ssh 作为远程 shell,这样所有的东西都被加密

--exclude='*.out' :排除匹配模式的文件,例如 *.out 或 *.c 等。

rsync 命令的例子

在这个例子中,从 ~/virt/ 目录递归地复制所有文件,但排除所有 *.new 文件:

$ rsync -av -e ssh--exclude='*.new'~/virt/ root@CentOS7:/tmp

示例输出:



Scp exclude files but using rsync exclude command

如果远程服务器上找不到 rsync,那么 rsync 命令将失败。在这种情况下,请尝试使用以下 scp 命令,该命令在当前目录中使用 bash shell 模式匹配 (它不能与 -r 选项一起使用):

$ ls

示例输出:

centos71.log centos71.qcow2 centos71.qcow2.new centos71.v2.qcow2.new meta-data user-data

复制除 .new 之外的当前目录中的所有内容:

$ shopt -s extglob

$ scp!(*.new) root@centos7:/tmp/

示例输出:

centos71.log 100%42621.3MB/s 00:00

centos71.qcow2 100%836MB32.7MB/s 00:25

meta-data 100%4718.5KB/s 00:00

user-data 100%1543569.7KB/s 00:00

有关更多信息,请参阅以下手册页:

$ man rsync

$ manbash

$ manscp

好了今天就到这里啦,大家明天见啦。
bashdb功能: 类似于GDB的调试工具,可以完成对shell脚本的断点设置,单步执行,变量观察等许多功能
【场合】: 脚本比较大时,通过-x参数调试时已不方便时.

【用法】:

bashdb -c script.sh
bashdb script.sh
bashdb --debugger script.sh
【说明】:该工具默认未安装,当前最新版本为:4.3-0.91,下载目录:http://bashdb.sourceforge.net/

1). 如果是ubuntu系统,直接用apt-get来安装
apt-get install bashdb

2). 如果是Readhat等版本,使用wget下载后,编译,安装,大致步骤如下:
wget https://sourceforge.net/projects/bashdb/files/bashdb/4.3-0.91/bashdb-4.3-0.91.tar.bz2
https://jaist.dl.sourceforge.net/project/bashdb/bashdb/4.4-0.94/bashdb-4.4-0.94.tar.gz
tar -xzvf bashdb-4.3-0.91.tar.bz2
cd bashdb-4.3-0.91
./configure
make && make install
【示例】:
【常用命令】

l             列出当前行以下的10行
q|quit        退出
h             帮助
/for/         向后搜索字符串for
?for?         向前搜索字符串for
x 1+2         计算算术表达式的值
!! ls -laRt   执行shell命令
n             执行下一条语句
s 4           单步执行4次,如遇到函数则进入函数里面
b 4           在行号4处设置断点
del 4         删除行号为4的断点
c 10          一直执行到行号10处  
R|run       重新执行当前调试脚本
finish        执行到程序最后


摘自:http://www.voidcn.com/article/p-sljifrsx-oo.html
https://morvanzhou.github.io
背景:有的人一台服务搞好几个PHP版本,麻烦,建议用Docker隔离~
由于系统环境变量之前同事安装的laravel是5.1...php默认的环境变量是:

不想破话原有环境变量,因为现在新的项目是laravel5.4.。。所以在用默认composer require安装时提示php版本过低滴问题
问题是这样滴:

默认composer安装会调用原来的php5.5环境变量,所以这里安装会出现兼容问题
新项目使用的是php7.1

那么如何在多个php版本中互不干扰安装composer呢,折腾了半个多小时,
现在说下解决办法吧:
1:下载composer.phar,官网有直接下载的链接,https://getcomposer.org/download/

2:composer.phar 复制到项目根目录,比如我的是:/home/www/web

3:执行 /usr/local/php7/bin/php composer.phar update (这里我的安装路径是/usr/local/php7/bin/php,不一定适合你额,请对号入座即可吧)

4:安装依赖包:/usr/local/php7/bin/php composer.phar require laravel/scout

OK,大功告成!


goto 性能好,但编译时间长。
技术一定要伴随需求的,有一个场景的。
工程师的社会责任。
做技术还是要懂业务。
Opcache回收问题:负载高的问题。影响稳定性。
Kafka
PHP-FPM能否解决数据库连接池的问题:
1)定时重启的机制。
2)Php-FPM重启一下。
3)要规避一下。(业务时间点)
粗放、性能高,内存搞得很精细,也很耗时。

Mysql的连接池,Kafka~
返回值在后面:Grep。(指函数返回值和C不一样)

autoconf版本太底~
makefile也是为了提高效率。
掌握知识不同,用的方法不同,本质是一样的。
关注生成这个扩展能否写出来,再看Autoconf,再看编译系统。
学一个语言成了研究这个编辑器的问题,要Forcus在那个点上。
做一件事表非常难非常难的时候,你得怀疑这样做对不对?

脖子肌肉不够强。
高性能PHP7~

终端用户的真实体验,才是应用性能是否良好的最终标准。
背景:用Windows下的Excel,再倒腾成Txt,在Linux下统计发现少一行,最后,用vi对最后一行的行尾按回车后再加一行,后删除这一行,再统计就对了,具体原因如下。
今天从一个服务器列表来批量执行expect脚本进行Tivoli Endpoint Client的安装,从excel表格中拷贝出服务器名导入到txt文件上传到服务器后,执行wc -l统计发现少了一行,反复对比确认不存在遗失的条目,那么为什么wc -l少一行呢?
查询帮助文件:
[root@managevm1 ~]# wc --help

-l, --lines            print the newline counts

-l用来统计新行的个数,那么用什么来标记新行的开始呢?对了!用换行符\n。于是用 vi编辑器打开txt文件,在最后一行的行尾回车下,然后ESC推出到命令模式,dd删除自然生成的最后一个空行。保存退出再次运行wc -l统计,这样就和excel中的行数一样了。

=============================================================
先简单介绍

wc(Word Count)命令的功能为统计指定文件中的字节数、字数、行数,并将统计结果显示输出

格式:wc file

命令参数:

-c 统计Bytes数(字节数),并显示文件名

-l 统计行数:使用换行符‘\n’作为行结束标志,实际是统计换行符个数

-m 统计字符数。这个标志不能与 -c标志一起使用。

-w 统计字数。一个字被定义为由空白、跳格或换行字符分隔的字符串。

-L 打印最长行的长度。

-help 显示帮助信息

--version 显示版本信息

实例:

wc test.txt

6  24 132test.txt

默认输出:行,字数,字节数



test.txt内容

Cat test.txt

test1 name1 age1 sex1

test2 name2 age2 sex2

test3 name3 age3 sex3

test4 name4 age4 sex4

test5 name5 age5 sex5

test6 name6 age6 sex6

问题:wc 统计行数时少一行:
因为wc ?l是按\n作为行结束符统计行数,所以最后一行如果没有\n的话会统计丢失。

实例:比如,在windows下生成同上面test.txt相同的文件testtt.txt,上传到linux下:
cat testtt.txt

test1 name1 age1 sex1

test2 name2 age2 sex2

test3 name3 age3 sex3

test4 name4 age4 sex4

test5 name5 age5 sex5

test6 name6 age6 sex6[wizad@srv26 lmj]$

可以看出结尾有点奇怪。这是因为文件末尾无\n,而是直接用了文件结束符EOF。这样文件使用wc统计就会少一行:

wc -l testtt.txt

5 24 136 testtt.txt

使用管道也不行:

cat testtt.txt | wc -l

5

为什么linux下没有这样的问题?
         因为vim编辑器会自动在文件结尾加上\n,在加上文件结束符EOF。(linux下文本文件主要按处理,所以vim会末行自动加\n)

而对windows文件用dos2unix转化也不行:
[wizad@srv26 lmj]$ dos2unix testtt.txt

dos2unix: converting file testtt.txt toUNIX format ...

[wizad@srv26 lmj]$ wc testtt.txt

5  24131 testtt.txt

可以看出windows文件在linux下还是有兼容问题的。文件字数没变24,byte数少5个是windows下行结束符是回车\r+换行\n。而linux下只是换行\n

Vim二进制可以看到不同,\n显示为.,文件结尾没有

来自:http://blog.csdn.net/sws9999/article/details/7942074
核心是模拟替换,用

记住,斜杠要转意,再就是是 sed -n 's#abc#def#p' replcee.txt  ==>  sed -i 's#abc#def#' replcee.txt 不要有g,如: sed -i #abc#def#g replcee.txt,出现没有被替换:
sed -n "s#,'pdo-mysql-php70-7.0.5'#123#p"  ./*.yml  #单引不行用双引,sed -n 's#,\'pdo-mysql-php70-7.0.5\'#123#p'  ./*.yml
真实的替换将123给去了:


&符号也要转义:

正确替换为:



上面也可以实现先模拟替换,再真实替换,更靠谱一些:
sed -n 's#\/data\/jenkins\/jobs\/jackxiang.com_deploy\/#\/data\/jenkins\/jobs\/jackxiang.com_deploy\/workspace\/#p'  *.yml
真的替换:
sed -i 's#\/data\/jenkins\/jobs\/jackxiang.com_deploy\/#\/data\/jenkins\/jobs\/jackxiang.com_deploy\/workspace\/#'  *.yml

nginx.lua2内容,给$upstream_response_time变量加上引号:
                    '"upstream_response_time":$upstream_response_time,'
sed -n 's@:$upstream_response_time@:"$upstream_response_time"@p' /usr/local/share/lua/5.1/kong/templates/nginx.lua2
                    '"upstream_response_time":"$upstream_response_time",'


替换一下PHP的SOCK文件位置,/usr/local/php/var/run/php-fpm.sock  ===>  /dev/shm/php-fcgi.sock:
cat /usr/local/php/etc/php-fpm.conf |grep php-fpm.sock
cat /usr/local/nginx/conf/vhost/*.conf|grep php-fpm.sock
新的:
cat /usr/local/php/etc/php-fpm.conf |grep php-fcgi.sock  
cat /usr/local/nginx/conf/vhost/*.conf|grep php-fcgi.sock

启动Nginx和PHP成功后删除软链接的sock文件:
ls -lart /usr/local/php/var/run/php-fpm.sock
rm -rf /usr/local/php/var/run/php-fpm.sock

ansible 10.70.32.33,10.70.32.32 -a"sed -i 's#\/usr\/local\/php\/var\/run\/php-fpm.sock#\/dev\/shm\/php-fcgi.sock#' /usr/local/nginx/conf/vhost/*.conf"

ansible 10.70.32.33,10.70.32.32 -a"sed -i 's#\/usr\/local\/php\/var\/run\/php-fpm.sock#\/dev\/shm\/php-fcgi.sock#' /usr/local/php/etc/php-fpm.conf"


cp -rf  /usr/local/php/etc/php-fpm.conf  /usr/local/php/etc/php-fpm.conf.bak.04.20
sed -i "s/\/usr\/local\/php\/var\/run\/php-fpm.sock/\/dev\/shm\/php-fcgi.sock/g" /usr/local/php/etc/php-fpm.conf
diff /usr/local/php/etc/php-fpm.conf.bak.04.20 /usr/local/php/etc/php-fpm.conf
service php-fpm restart

替换Nginx的配置文件:

批量测试:
ansible jack_vedio_upload -a"curl -i -H"Host:u.jackxiang.com" http://127.0.0.1/simpleupload.php"|grep 200 -B 2 > simpleupload.php.test.response.200.log


批量:

ansible 10.71.182.6 -a"sed -i 's/\/usr\/local\/php\/var\/run\/php-fpm.sock/\/dev\/shm\/php-fcgi.sock/g' /usr/local/php/etc/php-fpm.conf   && service php-fpm restart"

换成#号:
ansible 192.168.112.161 -a"sed -i 's#\/usr\/local\/php\/var\/run\/php-fpm.sock#\/dev\/shm\/php-fcgi.sock#g' /usr/local/php/etc/php-fpm.conf"


sed -n 's#\/usr\/local\/php\/var\/run\/php-fpm\.sock#\/dev\/shm\/php-fcgi\.sock#p' /usr/local/nginx/conf/vhost/*.conf


用ansible尝试批量替换#p ,注意显示内容:

ansible 10.71.182.6 -a"sed -n 's#\/usr\/local\/php\/var\/run\/php-fpm.sock#\/dev\/shm\/php-fcgi.sock#p' /usr/local/nginx/conf/vhost/*.conf"


正式开始批量替换:

ansible 10.71.182.6 -a"sed -i 's#\/usr\/local\/php\/var\/run\/php-fpm.sock#\/dev\/shm\/php-fcgi.sock#' /usr/local/nginx/conf/vhost/*.conf"

ansible xiyou -a"sed -i 's#\/usr\/local\/php\/var\/run\/php-fpm.sock#\/dev\/shm\/php-fcgi.sock#' /usr/local/nginx/conf/vhost/*.conf"  
ansible xiyou_api -a"sed -i 's#\/usr\/local\/php\/var\/run\/php-fpm.sock#\/dev\/shm\/php-fcgi.sock#' /usr/local/nginx/conf/vhost/*.conf"  
ansible xiyou_my -a"sed -i 's#\/usr\/local\/php\/var\/run\/php-fpm.sock#\/dev\/shm\/php-fcgi.sock#' /usr/local/nginx/conf/vhost/*.conf"  


<H2 class=post-title>用<FONT style="BACKGROUND-COLOR: #ffff00">awk</FONT>和sed实现批量替换文件中的控制字符</H2><DIV class=post-body>  有时候会遇到这样一个问题,就是把文件ftp上传到AIX系统以后,发现文件中包含了一些特殊的控制字符,例如最常见的^M。如果文件只是一个两个,那直接用vi打开文件,把文件中的控制字符替换掉就可以了。但如果文件数量很多的话,这样一个个去改就会变得很麻烦。这时候我们可以通过<FONT style="BACKGROUND-COLOR: #ffff00">awk</FONT>和sed实现对多个文件的批量处理,具体步骤如下:
1)假设需要修改的文件放在/tmp/test1目录下,然后新建一个目录,如/tmp/test2目录,这个目录用来存放修改后的文件。
ls -1 * &#124; <FONT style="BACKGROUND-COLOR: #ffff00">awk</FONT> '{print "sed 's/^M//g' "$1" &gt;/tmp/test2/"$1}' &gt; sed.sh
生成的脚本文件如下所示:<BR><div class=code>sed s/^M//g test.txt &gt;/tmp/test2/test.txt
sed s/^M//g test2.txt &gt;/tmp/test2/test2.txt
3)执行生成的脚本文件:
就会在/tmp/test2目录下生成去掉控制字符^M后的文件。
一些其他的方法可以参考以下的文章:
<U><FONT color=#0000ff>用sed批量替换文件中的字符</FONT></U></A>
<U><FONT color=#0000ff>批量修改文件</FONT></U></A>
<U><FONT color=#0000ff>sed的in-place edit选项,和RTFM</FONT></U></A>


方法1:
这两天在构建一个应用的使用用到了maven,由于project很大,足足有700多个pom.xml文件,更郁闷的是在很多pom.xml文件里都单独指定了资源库的url,我需要把这些资源库的url统一指定到nexus本地中央库.
手工一个个改文件配置有点不太实际,所以google了一下,找到批量替换文件内容的好方法,命令结构如下:
find -name '要查找的文件名' &#124; xargs perl -pi -e 's&#124;被替换的字符串&#124;替换后的字符串&#124;g'下面这个例子就是将当前目录及所有子目录下的所有pom.xml文件中的&#8221;http://repo1.maven.org/maven2&#8220;替换为&#8221;http://localhost:8081/nexus/content/groups/public&#8220;.
find -name 'pom.xml' &#124; xargs perl -pi -e 's&#124;http://repo1.maven.org/maven2&#124;http://localhost:8081/nexus/content /groups/public&#124;g'这里用到了Perl语言,
perl -pi -e 在Perl 命令中加上-e 选项,后跟一行代码,那它就会像运行一个普通的Perl 脚本那样运行该代码.
从命令行中使用Perl 能够帮助实现一些强大的、实时的转换。认真研究正则表达式,并正确地使用,将会为您省去大量的手工编辑工作。
find -name 'pom.xml' &#124; xargs perl -pi -e 's&#124;http://repo1.maven.org/maven2&#124;http://localhost:8081/nexus/content/groups/public&#124;g'

方法2:
Linux下批量替换多个文件中的字符串的简单方法。用sed命令可以批量替换多个文件中的字符串。
用sed命令可以批量替换多个文件中的字符串。
sed -i "s/原字符串/新字符串/g" `grep 原字符串 -rl 所在目录`
例如:我要把mahuinan替换为huinanma,执行命令:
sed -i "s/mahuinan/huinanma/g" 'grep mahuinan -rl /www'
这是目前linux最简单的批量替换字符串命令了!
具体格式如下:
sed -i "s/oldString/newString/g" `grep oldString -rl /path`
实例代码:sed -i "s/大小多少/日月水火/g" `grep 大小多少 -rl /usr/aa`
sed -i "s/大小多少/日月水火/g" `grep 大小多少 -rl ./`

方法3:
在日程的开发过程中,可能大家会遇到将某个变量名修改为另一个变量名的情况,如果这个变量是一个局部变量的话,vi足以胜任,但是如果是某个全局变量的话,并且在很多文件中进行了使用,这个时候使用vi就是一个不明智的选择。这里给出一个简单的shell命令,可以一次性将所有文件中的指定字符串进行修改:
grep "abc" * -R &#124; awk -F: '{print $1}' &#124; sort &#124; uniq &#124; xargs sed -i 's/abc/abcde/g'
[实践OK]Linux下使用find命令使用-exec 进行两次大括号传入路径进行cat重定向到对应的特定文件可结合xargs 相关命令:http://jackxiang.com/post/6520/
find超级查找,路径模糊、文件名模糊、时间、大小:

看文件名:https://linux.cn/article-6956-1.html ,使用 -l 选项可以只显示文件名。 ll  |grep ^d 只显示目录。
查找所有Conf文件包含了upstream的时间变量的文件列出来:

./nginx.conf

#删除/home/git/gitlab下所有系统日志(每周日11点59分删除一次所有日志)
59 23 * * 0 find /home/git/gitlab/log -name "*.log" -exec bash -c "echo '' > {}" \;


=============================================
这个解决方法我可是找了好久。。。正确写法:


find -name "*" -exec sh -c 'cat {} > {}.out.iso' \;
find -name "*.php" -exec bash -c "mv -f {} {}.tmp" \;
find -name "*.php" -exec bash -c "copy {} {}.tmp" \;
find -name "*.php" -exec bash -c "sed -e 's/aaa/bbb/' {} > {}.tmp; mv -f {}.tmp {}" \;

替换文件名内容:

find /tmp/exectest  -name "*.txt" -exec bash -c "ls {}" \;                    
/tmp/exectest/b.txt
/tmp/exectest/aaa/ccc.txt

find /tmp/exectest  -name "*.txt" -exec bash -c "ls {}|sed -e 's/txt/php/'" \;        
/tmp/exectest/b.php
/tmp/exectest/aaa/ddd.php






批量给不同层次的目录包含的*.log里写入jackwriteLog或清空日志:
find -name "*.log" -exec bash -c "echo '' > {}" \;
#删除/home/git/gitlab下所有系统日志(每周日11点59分删除一次所有日志)
59 23 * * 0 find /home/git/gitlab/log -name "*.log" -exec bash -c "echo "" > {}" \;
修改为这样:
#删除/home/git/gitlab下所有系统日志(每周日11点59分删除一次所有日志)
find /home/git/gitlab/log -name "*.log" -exec bash -c "echo "" > {}" \;



# find -name "*.log" -exec bash -c "echo 'jackwriteLog' > {}" \;        
# cat  ./k.log
jackwriteLog
# cat  ./n/n.log
jackwriteLog
# cat  ./n/j/a.log
jackwriteLog


find -name "*.php" -exec bash -c "cp {} {}.tmp" \;  
a.php  a.php.tmp  b.php  b.php.tmp



@ 2010-08-20 BS一下不看manpage的自己
引用
$ man sed
...
      -i[SUFFIX], --in-place[=SUFFIX]
              edit files in place (makes backup if extension supplied)
...
也就是说,只需要用 sed -i 就可以直接替换文件中的内容

======以前的分割线======

要用sed批量修改文件的内容,但是用这个命令解决不了问题:
find -name "*.php" -exec sed -e 's/aaa/bbb/' {} > {} \;
因为bash把 > 解释为find命令输出的重定向。
修改一下:
find -name "*.php" -exec sed -e 's/aaa/bbb/' {} \> {} \;
还是不行,因为 sed 去寻找一个名为 > 的文件进行处理
再修改:
find -name "*.php" -exec "sed -e 's/aaa/bbb/' {} \> {} " \;
还是不行,因为find去找一个名为 "sed -e 's/aaa/bbb/' {} \> {} " 的程序来执行
那是囧之又囧阿。于是去baidu,去google,
但是无论baidu还是google "find -exec 重定向"
都搜不到相应的解决方案,这样的问题居然没有人遇到过?
于是用google搜了一下
引用
linux find using "-exec" sed redirect

搜到了这一页: http://www.loisch.de/linux.html
看来还是国人太ooxx了,sigh。

解决方案其实很简单:绕个弯,把 -exec 的命令给shell来执行
注意:下面的命令一定不要在有用的文件上直接尝试!!!!!!
引用
find -name "*.php" -exec bash -c "sed -e 's/aaa/bbb/' {} > {}" \;

哦也!没有错误提示了!
然后 ls -al 一下,爽!所有文件大小都变成 0 了!
为什么捏?那篇文章里面解释了:
因为bash检测到需要重定向到那个文件,所以事先把那个文件清空了。
那篇文章里面提到一个修改bash配置的解决方案,但是不通用,建议还是用他说的第二种方案:
引用
find -name "*.php" -exec bash -c "sed -e 's/aaa/bbb/' {} > {}.tmp; mv -f {}.tmp {}" \;

嘿,这下爽了!
From:https://www.felix021.com/blog/read.php?1465




像下面这些文章只是说这么用,但从不说为何,在QQ群里说只一句重定向,没一个解释更深入点的,附录:
如何在-exec参数中使用重定向
http://www.2cto.com/os/201306/222794.html

Clear log file content without impacting service that is running (in batch):

find . -name "*.log" -exec bash -c ">{}" \;

Subsitute file content in batch:

find -name "*.xml" -exec bash -c "sed -e 's/aaa/bbb/' {} > {}" \;

http://blog.csdn.net/duanlove/article/details/8261677
在shell中,!$是一个特殊的环境变量,它代表了上一个命令的最后一个参数。
自己常常使用:Esc + . 和!$一样一样的。
$! 刚好写法相反,则表示Shell最后运行的后台Process的PID,看下面的例子:

mkdir -p /tmp/a/b/c/d/e/f
# ls !$
ls /tmp/a/b/c/d/e/f
# ls !$
ls /tmp/a/b/c/d/e/f
a.txt  b.txt  c.txt
# rm -Rf !$
rm -Rf /tmp/a/b/c/d/e/f
# ls !$
ls /tmp/a/b/c/d/e/f
ls: 无法访问/tmp/a/b/c/d/e/f: 没有那个文件或目录



Shell参数变量之 !:0是命令行,!:1是参数1,!:2是参数2,如下所示:

[root@justwinit-php-mysql_bj_sjs_10_44_202_177 ~]# echo hello world
hello world
[root@justwinit-php-mysql_bj_sjs_10_44_202_177 ~]# echo !:3
-bash: :3: bad word specifier
[root@justwinit-php-mysql_bj_sjs_10_44_202_177 ~]# echo hello world
hello world
[root@justwinit-php-mysql_bj_sjs_10_44_202_177 ~]# echo !:2
echo world
world
[root@justwinit-php-mysql_bj_sjs_10_44_202_177 ~]# echo !:1
echo world
world



例二:
# free -m
              total        used        free      shared  buff/cache   available
Mem:            991         856          32          34         103          29
Swap:          1407         321        1086

# free !:1
free -m              total        used        free      shared  buff/cache   available
Mem:            991         856          36          34          98          31
Swap:          1407         321        1086

===============================================
$ echo hello world
hello world
$ echo !$
echo worldworld
$ echo "hello world"
hello world
$ echo !$
echo "hello world"
hello world
这里为什么要用echo呢,请看下面,如果不用echo,!$输出的内容(world)会被shell当做一个命令来执行,所以就会报错
$ echo hello world
hello world
$ !$
world
No command 'world' found, did you mean:
Command 'tworld' from package 'tworld' (universe)
world: command not found
应用场景示例
1、建立多层目录并进入建立好的多层目录
$ mkdir -p a/b/c/d/e
$ cd a/b/c/d/e
改成
$ mkdir -p a/b/c/d/e
$ cd !$
上面mkdir -p命令用来一次性建立多层目录
2、编写文件后检测文件格式或者编译文件
$ vi a.php
$ php -l !$
或者
$ vi main.c
$ gcc !$

你可能不知道的超实用shell技巧 —— !$。
中,我们知道了 在shell中,!$代表了上一个命令的最后一个参数。那如果要获取上个命令的其它参数该怎么操作呢?
还是以echo hello world命令为例,下面就演示在该命令执行完成后,如何获取命令的各个参数甚至命令本身。
# echo helloworld
hello world
# echo !:1
echo hello
hello
# echo helloworld
hello world
# echo !:2
echo world
world
# echo hello world
hello world
# echo !:3
-bash: :3: bad word specifier
在调用!:3的时候出错了,因为上一次的命令只有两个参数。
下面你应该知道如何获取上次执行的是哪个命令了,那就是!:0,请看下面
# echo hello world
hello world
# echo !:0
echo echo
echo
其实呢,有更好的表示方法,看下面
# echo hello world
hello world
# echo !#
echo echo
echo
总结
!# 上一个命令名
!$ 上一个命令的最后一个参数
!:n 上一个命令的第n个参数
参考文章
http://crazyof.me/blog/archives/171.html
分页: 1/24 第一页 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 下页 最后页 [ 显示模式: 摘要 | 列表 ]