Bash 正则表达式查找和替换

发布于 2024-12-07 10:29:34 字数 394 浏览 0 评论 0原文

我不知道这是否可行,但是您可以动态更改查找/替换吗? 基本上我有这样的东西

<3 digit number> <data>

,我想做的是,如果数据与模式匹配,

<word>:<4 digit number>

则将 : 的所有实例(在整个文件中)替换为该行的 3 位数字 IE:

020 Word
021 Word:0001
Replace with 
020 021
021 0210001

Is this可以使用 AWK 或 Sed 吗? 如果不行,用C语言可以吗?

I don't know if this is possible, but can you dynamically alter a find/replace?
Basically I have something like this

<3 digit number> <data>

and what I want to do is if data matches the pattern

<word>:<4 digit number>

replace all instances (in the entire file) of <word>: with the line's 3 digit number I.E:

020 Word
021 Word:0001
Replace with 
020 021
021 0210001

Is this doable with AWK or Sed?
If not, is it doable in C?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

挽袖吟 2024-12-14 10:29:34

我知道这不是您所要求的,但我认为解决此问题的最佳方法是使用简单的 Perl 脚本。

#!/usr/bin/perl

$in= "input.txt";
$out= "output.txt";

# Buffer the whole file for replacing:
open(INFILE, $in);
@lines = <INFILE>;
open(INFILE, $in);

# Iterate through each line:
while(<INFILE>) {
  # If the line matches "word:number", replace all instances in the file
  if (/^(\d{3}) (\w+:)\d{4}$/) {
    $num = $1; word = $2;
    s/$word/$num/ foreach @lines;
  }
}

open(OUTFILE, $out);
print OUTFILE foreach @lines;

它看起来比实际需要的要长得多,因为我把它写得很好并且易于您阅读。

I know this isn't what you asked, but I think the best way to solve this is with a simple Perl script.

#!/usr/bin/perl

$in= "input.txt";
$out= "output.txt";

# Buffer the whole file for replacing:
open(INFILE, $in);
@lines = <INFILE>;
open(INFILE, $in);

# Iterate through each line:
while(<INFILE>) {
  # If the line matches "word:number", replace all instances in the file
  if (/^(\d{3}) (\w+:)\d{4}$/) {
    $num = $1; word = $2;
    s/$word/$num/ foreach @lines;
  }
}

open(OUTFILE, $out);
print OUTFILE foreach @lines;

It looks a lot longer than it really needs to be, because I made it nice and easy-to-read for you.

别念他 2024-12-14 10:29:34

我希望这次我答对了。

尝试以下内容:

#file name:t
kent$  cat t
020 Word
021 Word:0001

#first we find out the replacement, 021 in this case:
kent$  v=$(grep -oP "(\d{3})(?= Word:\d{4})" t|head -n1)

#do replace by sed:
kent$  sed -r "s/Word[:]?/$v/g" t                                                                                                        
020 021 
021 0210001

I hope this time I got you right.

try the stuff below:

#file name:t
kent$  cat t
020 Word
021 Word:0001

#first we find out the replacement, 021 in this case:
kent$  v=$(grep -oP "(\d{3})(?= Word:\d{4})" t|head -n1)

#do replace by sed:
kent$  sed -r "s/Word[:]?/$v/g" t                                                                                                        
020 021 
021 0210001
骷髅 2024-12-14 10:29:34
number=$(gawk --posix '/[0-9]{3} '${word}':[0-9]{4}/ { print $1; exit }' $file)

if [ "$number" != "" ]; then
    sed -r "s/${word}:?/${number}/" $file
fi
number=$(gawk --posix '/[0-9]{3} '${word}':[0-9]{4}/ { print $1; exit }' $file)

if [ "$number" != "" ]; then
    sed -r "s/${word}:?/${number}/" $file
fi
贪恋 2024-12-14 10:29:34

此 awk 解决方案需要两次遍历您的文件:一次查找所有需要替换的 Word,一次实际执行替换:

gawk '
    NR == FNR {
        if (match($2, /^([^:]+):[0-9][0-9][0-9][0-9]$/, a)) 
            repl[a[1] ":?"] = $1
        next
    }
    {
        for (word in repl)
            if ($2 ~ word) {
                sub(word, repl[word], $2)
                break
            }
        print
    }
' filename filename > new.file

需要 gawk 来捕获括号。

This awk solution takes 2 passes through your file: once to find all the Words needing replacement, and once to actually do the replacing:

gawk '
    NR == FNR {
        if (match($2, /^([^:]+):[0-9][0-9][0-9][0-9]$/, a)) 
            repl[a[1] ":?"] = $1
        next
    }
    {
        for (word in repl)
            if ($2 ~ word) {
                sub(word, repl[word], $2)
                break
            }
        print
    }
' filename filename > new.file

Requires gawk for capturing parentheses.

不甘平庸 2024-12-14 10:29:34

这是另一个 sed 解决方案:

# sweep the file and make a lookup table variable

lookup=$(sed -nr 's/(.*) (.*:).*/\2\1/p' <source_file |tr '\n' ' ')

# append the lookup to each line and substitute using a backreference
# N.B. remove the lookup whatever!

     sed -r "s/\$/@@${lookup}/;
             s/^(... )(.*)$@@.*\2:(\S*).*/\1\3/;
             s/^(... )(.*:)(.*)@@.*\2(\S*).*/\1\4\3/;
             s/@@.*//" <source_file

Here's another sed solution:

# sweep the file and make a lookup table variable

lookup=$(sed -nr 's/(.*) (.*:).*/\2\1/p' <source_file |tr '\n' ' ')

# append the lookup to each line and substitute using a backreference
# N.B. remove the lookup whatever!

     sed -r "s/\$/@@${lookup}/;
             s/^(... )(.*)$@@.*\2:(\S*).*/\1\3/;
             s/^(... )(.*:)(.*)@@.*\2(\S*).*/\1\4\3/;
             s/@@.*//" <source_file
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文