【shell】笔记|去重复行|删除匹配行|反选删除|反向显示|加减乘除

目录

目录

配置 bash Shell忽略命令大小写 |按“上“键显示该命令的历史

shell 删除匹配行

shell 获取结果中的第n列,第n行

grep过滤

shell 注释块

Linux反选删除文件

Linuxrm删除指定文件外的其他文件方法汇总

rm删除除去指定文件的剩余所有文件  (rm 反向删除)

linux 删除其他文件

如何反向选择文件并删除

反向显示文件

shell去除重复行

一、对整行比对去重复

二、对指定列比对去重复

shell按列排序

列column对齐

shell 定义分隔符和遍历行字段|IFS

shell 10进制转16进制

shell 加减乘除

shell 数组

显示历史命令和时间history

配置 bash Shell忽略命令大小写 |按“上“键显示该命令的历史

当按“上键”时,能够显示前一个历史命令。但是,这还 不太方便,下面的这个配置,可以让bash输入的命令头按“上“键显示该命令的历史,比如:输入 vim ,然后按”上“键,此时,可以显示上一次运行vim时

配置 linux 的 bash 忽略命令大小写 和 能根据输入的命令头按“上“键显示该命令的历史_nyist327的专栏-优快云博客

一般情况下,bash对命令是区分大小写的,当按“上键”时,能够显示前一个历史命令。但是,这还 不太方便,下面的这个配置,可以让bash忽略大小写,而且,能根据输入的命令头按“上“键显示该命令的历史,比如:输入 vim ,然后按”上“键,此时,可以显示上一次运行vim时的那条命令,非常的方便!

下面是该配置的内容,放在用户的home目录下面:

shibo@iZ94wlxkhx8Z:~$ cat .inputrc 
set completion-ignore-case on

#For single press Tab results for when a partial or no completion is possible
set show-all-if-ambiguous on

#For results when no completion is possible
set show-all-if-unmodified on

#History completion bound to arrow keys (down, up)
"\e[A": history-search-backward
"\e[B": history-search-forward

#Bash allows to quickly move between words with Ctrl+Left and Ctrl+Right
"\e[1;5C": forward-word
"\e[1;5D": backward-word
"\e[5C": forward-word
"\e[5D": backward-word
"\e\e[C": forward-word
"\e\e[D": backward-word"

shell 删除匹配行

sed -i '/ddd/d' abc.txt

shell 获取结果中的第n列,第n行

grep Version|awk ‘{print $2}’ |sed -n ‘1p’   #获取第2列,第1行

print 后带的是你要获取第几列,sed -n 后带的是指定第几行。

grep Version|awk ‘{print $2 $4 $8}’  #获取第2列、4列、8列

grep过滤

【shell】用 grep 查找包含字符串的文件|grep 过滤|取匹配行的前后n行_bandaoyu的note-优快云博客_grep查询包含关键字的文件

shell 注释块

方法四

 if false ; then 
    被注释的多行内容 
 fi

不能如下使用:

 if false ; then 
    #被注释的多行内容    不能加#
 fi
加载配置/定义/文件
     将函数或者变量替换定义在一个文件中,如函数可以定义在.fun文件中,然后在.sh脚本中,用“."加载,然后直接调用函数,如果:db.fun。定义函数可带参数,函数中的 $1,$2,$3…… 表示接受的第一个,第二个,第三个……参数。如:create_station_db  20   11   $1就是20  $2就是 11.
脚本中加载文件语句是:
GLOBAL_CFG_FILE = `find ./ |gropbal_config.sh`   #注意 "`"不是单引号
. ${GLOBAL_CFG_FILE}          #加载文件
${} 和$() 的区别
${NAME}和$NAME 都是引用替换变量NAME的替换内容,但是${}的好处就是限定了替换范围,不然${AB}C 用$ABC就容易产生歧义。
$(find ./ |grep global.cfg)和 `find ./ |grep global.cfg` 效果是一样的,但是有些shell上并不支持$()
删除指定范围内的字符串
sed -i ‘/#hwBegin/,/#hwEnd/d'  readme.txt   #就是将#hwBegin和#hwEnd 之间含#hwBegin/和/#hwEnd/
删除掉
覆盖和追究字符串
echo “hello” > readme.txt  #用hello覆盖 readme.txt的内容
echo “hello” 》readme.txt  #在 readme.txt的结尾追加“hello” 字符串
判断文件的后缀名是否是
   if[ "$ {sqlfile##*.}" ="sql" ]; then #判断文件的后缀名是否是sql,是就执行
来源:http://bbs.chinaunix.net/thread-624345-1-1.html
shell中的if else 语句
注意if、elif 和“[”之间要有空格
if [ ${SERVER_NAME} == ${HOPE_CLOUD_SERVER_NAME} ]; then
……
elif  [ ${SERVER_NAME} == ${HOPE_VIEW_SERVER_NAME} ]; then
……
else
……
fi
shell脚本带参数
shell 脚本可以跟着参数,在编写脚本的时候,在脚本中用$1表示跟着脚本命令后的第1个参数
$2 表示跟着脚本命令后的第2个参数
#如:执行 $2 指定的文件夹下面的(含子文件夹下面)的所以sql脚本的shell脚本如下:
function run_all_sql_script()
{
for  sqlfile   in `ls  $2`              #$2为第二个参数
do
    if [ -d $2'/'${ sqlfile} ]; then   # sqlfile   如果是个子文件夹 则 进入文件夹 递归
  
         run_all_sql_script()  $2'/'${ sqlfile}
    else
          if[ "$ {sqlfile##*.}" ="sql" ]; then #判断文件的后缀名是否是sql,是就执行
           
              mysql -u${MYSQL_USER}  -p${MYSQL_PASSWORD} $1< $2/${ sqlfile}
    
          fi
    fi
done
}
shell 循环输出目录下所有文件  
#!/bin/sh
function scandir(){

        for filename in `ls $1`
                do
                        if [ -d $1'/'$filename ] ; then
                                echo $1'/'$filename
                                scandir $1'/'$filename
                        else
                                echo $filename
                        fi
                done    
        
}


read file

scandir $file

#如果文件夹不存在,创建文件夹
if [ ! -d " /myfolder " ]; then
  mkdir / myfolder fi #shell判断文件,目录是否存在或者具有权限 folder= " /var/www/ "
file= " /var/www/log " # - x 参数判断 $folder 是否存在并且是否具有可执行权限 if [ ! -x " $folder "]; then
  mkdir " $folder "
fi # - d 参数判断 $folder 是否存在 if [ ! -d " $folder "]; then
  mkdir " $folder "
fi # -f 参数判断 $ file 是否存在 if [ ! -f " $file " ]; then
  touch " $file "
fi # - n 判断一个变量是否有值 if [ ! -n " $var " ]; then
  echo " $var is empty " exit 0
fi # 判断两个变量是否相等 if [ " $var1 " = " $var2 " ]; then
  echo ' $var1 eq $var2 '
else
  echo ' $var1 not eq $var2 '
fi
来源:http://www.cnblogs.com/emanlee/p/3583769.html
shell bash判断程序是否在运行
V1:

#!/bin/bash
ps_out=`ps -ef | grep $1 | grep -v 'grep' | grep -v $0`
result=$(echo $ps_out | grep "$1")
if [[ "$result" != "" ]];then
    echo "Running"
else
    echo "Not Running"
fi
$0 是命令本身 $1是第一个参数。-v 就是忽略到 -v后面含指定的内容行
V2:
processExist=`ps aux|grep processName|grep -v "grep" `
if [ -z $processExist ];then
    exec processName
else
    echo "process is running"
fi
if判断中的参数含义:
-z 是否为空
-d 是否为目录
类似这样的文件操作在shell编程中用处很大:我总结有一些一些经常使用
-d :判断制定的是否为目录
-z:判断制定的变量是否存在值
-f:判断制定的是否为文件
-L:判断制定的是否为符号链接
-r:判断制定的是否可读
-s:判断存在的对象长度是否为0
-w:判断制定的是否可写
-x:判断存在的对象是否可以执行
!:测试条件的否定符号
这些文件操作很多时候给脚本编程带来方便,尤其是用在if条件语句中

shell 查找并删除找到的文件/文件夹
删除指定目录下指定文件

find  要查找的目录名 -name .svn |xargs rm -rf

删除指定名称的文件或文件夹: find -type d | grep .svn$ | xargs rm -r

分析:

find -type d | grep .svn$ 通过此命令查找文件夹 过滤正则表达式中的目录

| xargs rm -r 执行删除指令


删除目录下所有exe文件


find  .  -name  '*.exe'  -type  f  -print  -exec  rm  -rf  {} ;
(1) "."    表示从当前目录开始递归查找

(2) “ -name '*.exe' "根据名称来查找,要查找所有以.exe结尾的文件夹或者文件

(3) " -type f "查找的类型为文件

(4) "-print" 输出查找的文件目录名

(5) 最主要的是是-exec了,-exec选项后边跟着一个所要执行的命令,表示将find出来的文件或目录执行该命令。

exec选项后面跟随着所要执行的命令或脚本,然后是一对儿{},一个空格和一个,最后是一个分号

find语句,每天运行以删除某个目录下7天以前的文件或目录
/bin/find /enterprisedb_backup/postgresql/ -mtime +7 -exec /bin/rm -rf '{}' \;
以上命令可能报错No such file or directory,需改成如下:
/bin/find /enterprisedb_backup/postgresql/ -mtime +7 -maxdepth 1 -exec /bin/rm -rf {} \;
详细解释见:http://m.blog.youkuaiyun.com/article/details?id=32151167
  1. 通过以上操作我们可以看到,find命令不单查询了/enterprisedb_backup/postgresql/目录,并且遍历了所有子目录,而此时子目录已经随着上一步母文件夹的删除而删除,所以找不到了。

解决方案:

  1. 整理思路后,可以确认,如果find只找出所需操作目录的第1层文件及目录即可解决此问题
  2. 通过伟大的 man 命令我们得到以下信息
     
  3. 测试操作确认修改为:
     
    这里意思是说:-mtime找到的信息可能会操过-maxdepth的范围,在find操作中建议-maxdepth放在所有其他参数的前面
shell 删除某个文件外的其他文件全部删除的命令

Linux反选删除文件

最简单的方法是

# shopt -s extglob      (打开extglob模式)
# rm -fr !(file1)
 
如果是多个要排除的,可以这样:
# rm -rf !(file1|file2) 

Linuxrm删除指定文件外的其他文件方法汇总

一、Linux下删除文件和文件夹常用命令如下: 删除文件: rm file
删除文件夹: rm -rf dir
需要注意的是, rmdir 只能够删除 空文件夹。 二、删除制定文件(夹)之外的所有文件呢?
1、方法1,比较麻烦的做法是:
复制需要保留的文件到其他文件夹,然后将该目录删除, 然后将需要保留的移动 回来。 mv keep ../ #保留文件(夹) keep
rm -rf * #删除当前文件夹里的所有文件 mv ../keep ./ #将原来的东西移动回来
2、方法2,需要在当前文件夹中进行:
rm -rf !(keep) #删除keep文件之外的所有文件
rm -rf !(keep1 | keep2) #删除keep1和keep2文件之外的所有文件
3、方法3,当前文件夹中结合使用grep和xargs来处理文件名: ls | grep -v keep | xargs rm #删除keep文件之外的所有文件
说明: ls先得到当前的所有文件和文件夹的名字, grep -v keep,进行grep正则匹配查找keep,-v参数决定了结果为匹配之外的结果,也就是的到了keep之外的所有文件名,然后 xargs用于从 标准输入获得参数 并且传递给后面的命令,这里使用的命令是 rm,然后由rm删除前面选择的文件。
好处:使用了grep来正则表达式来匹配文件名字,可以一次保留多个文件,从而进行更加准确的处理。
4、方法4,使用find命令代替ls,改进方法3从而能够处理制定文件夹的文件:
find ./test/ | grep -v keep | xargs rm #删除当前test文件夹中keep文件之外的所有文件
说明,用grep而不用find -name选取名字,因为find选取名字时比较麻烦,对正则表达式支持不够,无法排除指定文件名。
5、方法5,直接使用find命令删除其他文件:
find ./ -name '[^k][^e][^e][^p]*'  -exec rm -rf {} \; #删除keep以外的其他文件。 find ./ -name '[^k][^e][^e][^p]*'  | xargs rm -rf  #删除keep以外的其他文件。推荐!
说明:上面第二行的代码效率高些,原因在于删除多个文件时 -exec会启动多个进程来处理,而xargs会启动一个rm进程来处理。
关于find 执行命令的效率和借用xargs启动的命令效率的比较,详情请参考:http://www.linuxsir.org/main/?q=node/137
Linux文件查找命令find,xargs详述  http://www.linuxsir.org/main/?q=node/137 本文转载自:http://blog.sina.com.cn/s/blog_70ffb5c501011rrk.html
 

rm删除除去指定文件的剩余所有文件  (rm 反向删除)

zhou@zhou:~/LinuxC/file/test$ ls
1  23sdfwe 88888888  aabb ag   ghdda    mmm
2 3       aaaaaaaa abc  asdg  llllllll wwwww
zhou@zhou:~/LinuxC/file/test$

然后我想删除除了包含字符串aa外所有的文件,也就是想留下aabb,aaaaaaaa,这两个文件, 其他的全部删除
下面是我的命令:

zhou@zhou:~/LinuxC/file/test$ rm `ls | grep -v"aa"`
zhou@zhou:~/LinuxC/file/test$ ls
aaaaaaaa  aabb
zhou@zhou:~/LinuxC/file/test$
所以了,成功了。
简单的解释一下那条命令吧:rm 删除后面指定的文件
`ls | grep -v "aa" ` 记得外面是反引号( 反引号的位置就在标准键盘的数字1的左边)
ls:查看当前目录下所有的文件,使用grep命令过滤一下grep -v "aa" 就是找出字符串中不带“aa”的。

整体再顺一下:列出文件名不带“aa”串的文件,然后删除他们。OK。
其实说起来简单,当时我也做了好长时间,因为以前没怎么接触grep,因此一开始我想到的办法是使用 正则表
达式,但是在做的过程中突然发现了grep使个不错的东西,因此就使用了。

上面的命令使删除带有“aa”串的文件,那如果我只想留下文件aa呢?很简单

zhou@zhou:~/LinuxC/file/test$ rm `ls | grep -v"^aa$" `
在aa前面加上^,后面加上$表示结束符的意思,这个就是完全匹配了。
好了,就这么多。但愿以后能用到这个有用的命令
转自:http://blog.sina.com.cn/s/blog_67e34ceb01014930.html

linux 删除其他文件

http://zhidao.baidu.com/link?url=uvHfrb3kSnM_8p5ILhZyc39U0h3md-Ncrm3iaygeYTLU-zjthNBlqO674VulVGTnPiNcl2nj7wo5vn08N4481_

求教 linux centos我想删除某目录中文件名不符合"*20100330*"这样规则的文件应该怎么删除?

假设目录名为myTest且为当前目录的下一级目录,使用如下命令即可:
cd ./myTest && rm `ls | grep -v '20100330'` && cd ..

进入myTest目录,删除文件后返回当前目录。

grep的-v参数表示反向选择。

一般使用rm删除文件的时候会有确认提示,如果不要确认,直接强制删除,可以使用rm的-f参数。

其他1条回答

find ./ -type f \! -name "*20100330*" -exec rm -rf {} \;

如何反向选择文件并删除

http://bbs.youkuaiyun.com/topics/390077765

案例:一个文件夹下我想删除 除了abc文件 之外的所有文件,命令怎么写(linux下)

find . -maxdepth 1 -type f -not -name 'abc' -exec rm '{}' ';'

ls | grep -v abc | xargs -i rm -rf {}

rm -f `ls | grep -v abc`
如果文件很多的情况下,不要用这种方法……
要用2楼的方法……

mv abc /tmp
rm *
mv /tmp/abc .

反向显示文件

使用ls命令仅仅显示当前目录不包括.的文件.

ls加grep过滤的方式:ls -al | grep -v '\.'(ls --ignore=.* -al也可实现)。

在打开extglob模式下(缺省是打开的),ls也可以实现,而且更加灵活.

shopt -u extglob #关闭
shopt -s extglob #打开

ls -al !(*.*)
ls -al -d !(*.*)

删除文件时排除特定文件

删除当前目录下所有 *.txt文件,除了test.txt

1
2
3
4
5
6
7
8
rm ` ls *.txt| egrep - v test .txt`
#或者
rm ` ls *.txt| awk '{if($0 != "test.txt") print $0}' `
#排除多个文件
rm ` ls *.txt| egrep - v '(test.txt|fff.txt|ppp.txt)' `
rm -f ` ls *.log.1| egrep - v '(access-2010-09-06.log|error-2010-09-06.log)' `
rm -f ` ls *.log| egrep - v '(access-2010-09-06.log|error-2010-09-06.log)' `
rm -f ` ls *.log| egrep - v '(20100906.log)' `

注意:上面所用的符号是‘`’,而不是单引号

这里是用ls得到原始数据,也可以用find命令

rm `find . -name *.txt | egrep -v ‘(test.txt|fff.txt|ppp.txt)'`

==========================================

egrep是grep的扩展, egrep除了具备grep的基本功能外还可以使用附加的正则表示式元字符, 如

[a-z]+A

[a-z]?A

[a-z]|[a-z]

abc(d|e)

等, 另外egrep不允许使用\(\)和\{\}(摘自:http://www.pythontab.com/html/2013/linuxkaiyuan_0205/214.html)

Shell while read命令完成用户的交互输入》

Shell while read命令完成用户的交互输入_Harvey-优快云博客_shell while 输入

shell去除重复行

一、对整行比对去重复

排序后去重(原行顺序打乱)

sort -u test.txt

sort test.txt|uniq

sort -n aa.txt | uniq   > bb.txt

grep -nR " handle_osd_ping"  ceph-osd.3.log|sort |uniq

注:uniq只对相邻行做比较,所以要先sort先排序下以使重复行相邻,才能完成去重复

保持原行间相对顺序去重

awk ‘!a[$0]++’ test.txt

shell删除重复行_shell 去重复行_https://blog.youkuaiyun.com/qq_24889005/article/details/123769717

二、对指定列比对去重复

sort方法

 Linux sort 排序命令&&uniq去重复;https://www.jianshu.com/p/c9f79d7caa66

sort -t $'\t' -k 3,3 -u filename #​-t 指定分隔符为‘\t’
sort -t ' ' -k 3,3 -u filename #​-t 指定分隔符为' '

sort -t ',' -k 1,1 -u

其中 -t 指定列之间的分隔符, -k 指定从第几列到第几列作为去重标准

linux sort 按列去重:https://blog.youkuaiyun.com/wqfhenanxc/article/details/81937584

awk方法

awk ‘!a[$6]++’ test.txt

依据第六列进行去重复

shell按列排序

sort 排序命令
-t 指定分隔符
-k 指定第三列排序
-u 去重

sort的其他一些选项:
-r 降序排列

-n 看为数字来比较  (如果按字符比较10 比2小,因为第一个字符比2小)

列column对齐


可以将文本结果转换为整齐的表格,上下对齐

命令: Column


使用的参数:
-t :表格,默认以空格间隔
-s:需要配合-t使用,指定分隔符

实例:

未对齐:

[oracle@db ogg]$ (echo info all;echo exit)|./ggsci|grep -E "EXTRACT|REPLICAT" |awk 'BEGIN {FS=" +"} {print $3,$2,$4,$5}'


DP_XNJC RUNNING 00:00:00 00:00:04
XNJC RUNNING 00:00:00 00:00:07

对齐
[oracle@db ogg]$ (echo info all;echo exit)|./ggsci|grep -E "EXTRACT|REPLICAT" |awk 'BEGIN {FS=" +"} {print $3,$2,$4,$5}' |column -t


DP_XNJC   RUNNING  00:00:00  00:00:06
XNJC          RUNNING  00:00:00  00:00:09
 

shell 定义分隔符和遍历行字段|IFS

例如将IP 192.169.31.166转十六进制,IFS="."  以“.”为分隔符

ip_to_hex2.sh

function ip4_to_hex()
{

hexip=""
IFS="."  
num=0

for str in $1
do
ip[num]=${str}
((num++))
done

hexip=`printf "%x%x:%x%x" ${ip[0]} ${ip[1]} ${ip[2]} ${ip[3]}`

}

./ip_to_hex2.sh 192.169.31.166

shell 10进制转16进制

dec2hex(){
    printf "0x%x" $1
}

a=$(dec2hex 2131165531)
echo $a

shell 加减乘除

#!/bin/bash
a=$1
b=$2
echo a+b=$(($a+$b))
echo a-b=$(($a-$b))
echo a*b=$(($a*$b))
echo a/b=$(($a/$b))
echo a%b=$(($a%$b))
echo a**b=$(($a**$b))

上面优化版

#!/bin/bash
echo $1=(($1)) 
echo $((3==4)) 不相等结果为0 相等结果为1
#/bin/bash

a=1
while [ $a -le 100 ] #((a<=100))
  do
    let sum=sum+a #((sum+=a))
    let a++             #((a++))
done
echo $sum

浮点数

shell计算中使用除法,基本默认上都是整除。
比如:
num1=2
num2=3
num3=`expr $num1 / $num2`
这个时候num3=0 ,是因为是因为expr不支持浮点除法
解决的方法:
num3=`echo "sclae=2; $num1/$num2" | bc`
使用bc工具,sclae控制小数点后保留几位
还有一种方法
awk 'BEGIN{printf "%.2f\n",’$num1‘/’$num2‘}'
如果用百分比表示
awk 'BEGIN{printf "%.2f%\n",(’$num1‘/’$num2‘)*100}'

shell 数组

Shell 数组 | 菜鸟教程

显示历史命令和时间history

history 显示历史命令

让 history 命令显示日期和时间

echo 'HISTTIMEFORMAT="%F %T "' >> /etc/profile

source /etc/profile

<think>好的,我现在需要帮助用户解决如何在shell中给文本文件的最后一拼接一个“|”字符的问题。首先,我需要理解用户的需求。他们可能有一个文本文件,需要在最后一的末尾添加一个竖线符号。这可能是因为某些数据格式要求,比如某些CSV或表格数据需要每以分隔符结束,包括最后一。 接下来,我要考虑用户的使用场景。用户可能是在处理数据导出,或者在准备某种需要特定格式的文件。比如,之前用户询问过GaussDB的COPY命令导出数据时末尾添加分隔符的问题,现在可能是在处理导出的文件后续操作,或者在另一个环节需要确保每都有分隔符结尾,包括最后一。这种情况下,用户可能已经有一个文件,但发现最后一缺少分隔符,需要补上。 然后,我需要思考如何用shell命令实现这个需求。常见的方法包括使用sed、awk或者其他文本处理工具。我需要回顾这些工具的用法,找出最有效的方法。 首先想到的是sed。sed可以在处理文本时进替换、添加等操作。但默认情况下,sed是按处理的,要在最后一添加字符,需要匹配最后一,并在其末尾加上“|”。可以使用地址符号$来匹配最后一,然后使用替换命令s/$/|/,将尾替换为“|”。但是需要注意,如果最后一的换符存在问题,比如没有换符,可能会导致问题。这时候可能需要先确保最后一有换符,或者处理这种情况。 另一个工具是awk。awk可以逐处理文件,并且在END块中处理最后一。可以记录最后一,在处理结束后输出并添加“|”。这种方法可能更灵活,特别是当文件很大时,避免将整个文件读入内存。不过对于小文件来说,两种方法效率差不多。 另外,可能需要考虑文件是否以换符结束。如果文件最后一没有换符,直接添加“|”可能会导致问题。比如,使用sed时,如果最后一没有换符,替换命令可能不会生效。这时候可能需要先添加一个换符,或者在处理时考虑这种情况。例如,使用sed的a命令来追加内容,但需要处理地址匹配。 然后,我需要验证这些方法的正确性。比如,测试一个示例文件,包含多,最后一有或没有换符的情况,看看命令是否都能正确工作。例如,对于文件: line1 line2 line3 运命令后,最后一变成line3|。如果原文件最后一没有换符,比如: line1 line2 line3 (没有最后的换符),这时候sed的替换命令是否有效?可能需要先确保文件以换符结束,或者在处理时考虑这种情况。 此外,用户可能需要直接修改原文件,而不是输出到标准输出。这时候需要在命令中加入-i项(对于sed)或者定向到临时文件再替换原文件。 还需要考虑不同系统上的工具差异,比如macOS上的sed和GNU sed的区别,可能需要使用不同的参数,比如在macOS中使用-i时需要指定备份扩展名,而Linux中可以不带。用户可能是在哪种环境下操作呢?可能需要给出通用的方法,或者提醒用户注意系统差异。 总结可能的解决方案: 1. 使用sed:`sed '$s/$/|/' file`,这会匹配最后一,并在尾添加“|”。但如果最后一没有换符,可能导致“|”被添加到尾但后面没有换符,或者可能不会正确匹配。需要处理这种情况。 2. 使用awk:`awk '{if (NR>1) print prev; prev=$0} END {print prev "|"}' file`,这种方法会逐处理,记录前一的内容,最后处理最后一时添加“|”。 3. 使用echo或printf在最后添加,但需要先判断最后一是否存在,可能需要组合其他命令,比如tail和head。 但直接修改文件的话,可能需要用到临时文件或者-i项。 现在需要给出具体的步骤,以及注意事项,比如备份原文件,处理没有换符的情况等。 可能还需要提供多种方法,让用户根据自己的情况择。比如,使用sed的方法简单,但可能在最后一没有换符时有问题;使用awk的方法更可靠,但命令稍复杂。 此外,用户可能希望直接修改原文件,所以需要给出sed的-i项用法,例如`sed -i '$s/$/|/' file`,但注意在macOS中需要写成`sed -i '' '$s/$/|/' file`。 另外,如果文件为空,这些命令是否会有问题?比如,如果文件没有内容,添加“|”会导致错误吗?可能需要考虑这种情况,或者提醒用户处理空文件的情况。 总结回答的结构: 1. 使用sed的方法,说明命令和可能的注意事项,如换符和系统差异。 2. 使用awk的方法,说明如何处理最后一。 3. 其他方法,比如使用组合命令。 4. 注意事项,如备份文件,处理空文件,换符问题等。 5. 示例测试,验证命令的正确性。 现在需要将这些思路整理成清晰的步骤,确保用户能够理解并正确执命令。同时,需要确保命令的正确性,避免出现语法错误或逻辑错误。</think>在 Shell 中为文本文件最后一末尾添加 `|` 字符,可通过多种方法实现。以下是分步骤解决方案及注意事项: --- ### **方法1:使用 `sed` 直接修改文件** #### 步骤说明 1. **基础命令**(兼容 GNU sed): ```bash sed -i '$s/$/|/' filename # 在最后一末尾添加 | ``` - `-i`:直接修改原文件 - `$`:匹配最后一 - `s/$/|/`:将尾替换为 `|` 2. **macOS 系统需调整**(BSD sed): ```bash sed -i '' '$s/$/|/' filename # macOS 必须指定备份扩展名(此处为空) ``` #### 示例验证 - **原始文件**: ```plaintext line1 line2 line3 ``` - **执命令后**: ```plaintext line1 line2 line3| ``` --- ### **方法2:使用 `awk` 精准处理** #### 步骤说明 ```bash awk 'NR>1 {print prev} {prev=$0} END {print prev "|"}' filename > tmpfile && mv tmpfile filename ``` - `NR>1 {print prev}`:逐缓存,从第二开始打印前一 - `END {print prev "|"}`:处理最后一时追加 `|` - 需定向到临时文件再覆盖原文件 #### 示例验证 - **原始文件**: ```plaintext header data1 data2 ``` - **执命令后**: ```plaintext header data1 data2| ``` --- ### **方法3:组合 `head` 与 `echo`** #### 步骤说明 ```bash { head -n -1 filename; tail -n 1 filename | sed 's/$/|/'; } > tmpfile && mv tmpfile filename ``` - `head -n -1`:提取除最后一外的所有内容 - `tail -n 1`:提取最后一并通过 `sed` 追加 `|` - 合并后覆盖原文件 --- ### **注意事项** 1. **换符问题**: - 若文件最后一**没有换符**,`sed` 可能无法正确追加 `|`。可先标准化文件格式: ```bash sed -i -e '$a\' filename # 确保最后一有换符 sed -i '$s/$/|/' filename ``` 2. **空文件处理**: - 若文件为空,直接操作会失败。建议添加检查: ```bash if [ -s filename ]; then sed -i '$s/$/|/' filename else echo "|" > filename # 按需初始化 fi ``` 3. **备份原文件**: ```bash cp filename filename.bak # 操作前备份 ``` --- ### **扩展场景** #### 场景1:批量处理目录下所有 `.txt` 文件 ```bash find . -name "*.txt" -exec sed -i.bak '$s/$/|/' {} \; ``` #### 场景2:仅在最后一无 `|` 时追加 ```bash last_line=$(tail -n 1 filename) if [[ ! "$last_line" =~ \|$ ]]; then sed -i '$s/$/|/' filename fi ``` --- ### **验证测试** ```bash # 生成测试文件 echo -e "apple\nbanana\ncherry" > test.txt # 执命令 sed -i '$s/$/|/' test.txt # 查看结果 cat test.txt ``` **输出**: ```plaintext apple banana cherry| ``` --- 择适合场景的方法即可。若需高可靠性,推荐使用 `awk`;若追求简洁,`sed` 是更优择。操作前务必做好备份!
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值