AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / unix / 问题 / 416786
Accepted
Arcticooling
Arcticooling
Asked: 2018-01-14 02:45:36 +0800 CST2018-01-14 02:45:36 +0800 CST 2018-01-14 02:45:36 +0800 CST

如果文件中不存在这些行,如何将多行附加到文件中?

  • 772

如果文件中不存在这些行,如何将多行附加到文件中?

例如,要添加多个全局别名,/etc/bash.bashrc我使用heredocument:

cat <<-"BASHRC" >> /etc/bash.bashrc
    alias rss="/etc/init.d/php*-fpm restart && systemctl restart nginx.service"
    alias brc="nano /etc/bash.bashrc"
BASHRC

我被批评说这个操作不包括检查行是否已经存在的方法,如果错误地重新执行 heredocument,我可能会导致冗余以及冲突。

shell-script text-processing
  • 6 6 个回答
  • 2145 Views

6 个回答

  • Voted
  1. Best Answer
    ilkkachu
    2018-01-18T06:48:38+08:002018-01-18T06:48:38+08:00

    用于将文件中的行添加newdata到datafile. 更改newdata为 here-doc 应该很简单。这实际上不是很有效,因为它需要grep每个(新)输入行:

    target=datafile
    while IFS= read -r line ; do
        if ! grep -Fqxe "$line" "$target" ; then
            printf "%s\n" "$line" >> "$target"
        fi
    done < newdata 
    

    对于每一行,我们使用grep它来查看它是否已经存在于目标文件中,-F用于固定字符串匹配(无正则表达式),-x用于全行匹配,并-q抑制匹配行的输出。grep如果没有找到匹配的行,则返回虚假错误代码,因此如果否定结果为真,则附加到目标文件。


    更有效地,在awk. 这依赖于awk能够将任意行作为数组的键来处理。

    $ awk 'FNR == NR { lines[$0] = 1; next } ! ($0 in lines) {print}' datafile newdata 
    

    第一部分FNR == NR { lines[$0] = 1; next }将第一个输入文件的所有行作为键加载到(关联)数组lines中。第二部分! ($0 in lines) {print}在以下输入行上运行,如果该行不在数组中,则打印该行,即“新”行。

    结果输出仅包含新行,因此需要将其附加到原始文件中,例如sponge:

    $ awk 'FNR == NR { lines[$0] = 1; next } ! ($0 in lines) {print}' datafile newdata | sponge -a datafile
    

    或者我们可以awk将这些行附加到最后一行,它只需要将文件名传递给awk:

    $ target=datafile 
    $ awk -vtarget="$target" 'FNR == NR { lines[$0] = 1; next } 
                            ! ($0 in lines) {print >> target}' "$target" newdata
    

    要将 here-doc 与 一起使用,除了设置重定向之外awk,我们还需要将(stdin) 添加为显式源文件,因此-awk ... "$target" - <<EOF

    • 4
  2. B Layer
    2018-01-14T03:28:01+08:002018-01-14T03:28:01+08:00

    该解决方案可能与您的想法略有不同,但我会检查是否实际定义了别名,如果没有,则仅将其添加到 bashrc 中。假设您使用的是相对最新的 Bash 版本...

    # instead of 'alias x=y' form put them in an associative array
    declare -A aliases
    aliases['a']='apple'
    aliases['ba']='banana'
    
    for key in "${!aliases[@]}"; do
        if ! alias "$key" > /dev/null 2>&1; then
            printf "alias %s='%s'\n" "$key" "${aliases[$key]}" >> /etc/bash.bashrc
        fi
    done
    
    unset aliases key
    

    源它. ./scriptname而不是作为普通脚本运行它。

    注意:如果您有一堆候选别名并且对手动将它们转换为关联数组形式持谨慎态度,那么您可以使用编辑文件vim并运行以下命令::%s/\valias *([^=]+)\=['"]?([^'"]+)['"]?$/aliases['\1']='\2'/.

    或将您的候选别名(仅此而已)放在一个文件中(例如/tmp/aliases.txt),然后aliases[..]='..'将脚本中的行替换为:

    while IFS= read -r a; do 
        eval "$a"; 
    done < <(sed -E "s/alias  *([^=]+)=['\"]?([^'\"]+)['\"]?$/aliases['\1']='\2'/" /tmp/aliases.txt)
    

    当然,除了使用 AA 之外,还有其他方法,但它们干净且易于使用……我现在全力以赴。:)

    • 3
  3. Hauke Laging
    2018-01-14T09:14:24+08:002018-01-14T09:14:24+08:00

    完全匹配的通用解决方案(未针对性能进行优化);该文件input包含要检查的行:

    awk 'FNR==NR { lines[NR]=$0; next; };
        { for(i=1;i<=length(lines);i++) if ($0==lines[i]) matches[i]=1; print; };
        END { for(i=1;i<=length(lines);i++)
            if (matches[i]==0) print lines[i]; }' input file
    

    测试:

    :> cat input
    alias rss="/etc/init.d/php*-fpm restart && systemctl restart nginx.service"
    alias brc="nano /etc/bash.bashrc"
    
    :> cat file
    a
    b
    c
    alias rss="/etc/init.d/php*-fpm restart && systemctl restart nginx.service"
    d
    

    命令的输出awk:

    a
    b
    c
    alias rss="/etc/init.d/php*-fpm restart && systemctl restart nginx.service"
    d
    alias brc="nano /etc/bash.bashrc"
    
    • 1
  4. B Layer
    2018-01-18T14:50:47+08:002018-01-18T14:50:47+08:00

    嗯。这个怎么样...

    将别名添加到文件new中。然后...

    cp bashrc bashrc.tmp && comm -23 <(sort -u new) <(sort -u bashrc.tmp) >> bashrc && rm -f bashrc.tmp
    

    我们对新别名和bashrc内容进行唯一排序(放入临时文件以避免在追加到bashrc时出现竞争条件)并通过comm. comm对已排序的文件进行逐行比较,并显示唯一和常见的行。我们抑制了第 2 列和第 3 列 ( -23),因此结果只是那些对new唯一的行,我们将它们附加到bashrc。而已。

    (这是一种与我的其他答案完全不同的方法,专注于您对更多“单线”的追求。)

    • 0
  5. kenichi
    2018-01-20T10:47:07+08:002018-01-20T10:47:07+08:00

    附加行的顺序重要吗?

    如果没有,您可以尝试这样的解决方案:

    comm -1 -3 <(sort /etc/bash.bashrc) <(sort aliases) >> /etc/bash.bashrc
    

    假设您以前保存了要添加到文件中的行aliases。

    comm是 GNU coreutil(您可以查看它的手册页),它允许逐行比较两个已排序的文件。

    • 0
  6. Manu T G
    2020-10-02T00:01:06+08:002020-10-02T00:01:06+08:00
    filename='openFileLimit.txt'
    while read p; do
        if grep "$p" /target/file/and/path; then
                echo "$p already present"
        else
                echo "$p" >> /target/file/and/path
        fi
    done < $filename
    
    • 0

相关问题

  • 通过命令的标准输出以编程方式导出环境变量[重复]

  • 按分隔符拆分并连接字符串问题

  • 多行文件洗牌

  • MySQL Select with function IN () with bash array

  • 如何更改字符大小写(从小到大,反之亦然)?同时[重复]

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    ssh 无法协商:“找不到匹配的密码”,正在拒绝 cbc

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    如何卸载内核模块“nvidia-drm”?

    • 13 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Wong Jia Hau ssh-add 返回:“连接代理时出错:没有这样的文件或目录” 2018-08-24 23:28:13 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST
  • Martin Hope
    Bagas Sanjaya 为什么 Linux 使用 LF 作为换行符? 2017-12-20 05:48:21 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve