使用bash替换从两行之间开始的字符串

时间:2016-12-08 02:38:53

标签: bash shell awk sed

有没有办法在不使用循环的情况下使用sed替换整个文件中字符串的开头?

例如,我的源数据如下:

str_address: 123 main street
str_desc: Apt3
str_desc: 2nd floor
str_city: new york
str_desc: mailing address

现在,该文件将包含数千个地址,但我希望随时“ str_desc ”出现在“ str_address ”之后和之前 str_city “替换为” str_address “,但出现的任何” str_desc “在 str_city 之后保持不变。

期望的输出:

str_address: 123 main street
str_address: Apt3
str_address: 2nd floor
str_city: new york
str_desc: mailing address

我可以使用

提取此信息
cat file | awk '/str_city/{f=0} f; /str_address/{f=1}'

给出了

str_desc: Apt3
str_desc: 2nd floor

但我无法将第一个“ str_desc ”更改为“ str_address ”。

2 个答案:

答案 0 :(得分:2)

您在awk提取代码中几乎拥有完整的解决方案:

awk '/str_city/{f=0} f; /str_address/{f=1}'

这个想法是:

  • 当您看到str_address
  • 时打开旗帜
  • 当您看到str_city
  • 时,请关闭此标记 如果标志已开启,则
  • str_desc替换为str_address

基本上(可读形式,顺序很重要):

awk '
    $1 == "str_address:"           { flag = 1 }
    $1 == "str_desc:" && flag == 1 { $1 = "str_address:" }
    $1 == "str_city:"              { flag = 0 }
                                   { print }
    ' < inputFile >outputFile

这里有一份成绩单,显示了它的实际效果:

pax$ echo '
     str_address: 123 main street
     str_desc: Apt3
     str_desc: 2nd floor
     str_city: new york
     str_desc: mailing address
     ' | awk '
         $1 == "str_address:"           { flag = 1 }
         $1 == "str_desc:" && flag == 1 { $1 = "str_address:" }
         $1 == "str_city:"              { flag = 0 }
                                        { print }'

str_address: 123 main street
str_address: Apt3
str_address: 2nd floor
str_city: new york
str_desc: mailing address

当然还有缩小版本:

awk '$1=="str_address:"{f=1}$1=="str_desc:"&&f==1{$1="str_address:"}$1=="str_city:"{f=0}{print}' < inputFile >outputFile

答案 1 :(得分:1)

您可以在sed中使用地址范围:

$ sed '/str_address/,/str_city/s/str_desc/str_address/' infile
str_address: 123 main street
str_address: Apt3
str_address: 2nd floor
str_city: new york
str_desc: mailing address

这会使str_desc范围之外的所有/str_address/,/str_city/保持不变,并将其他str_address替换为s/str_desc/str_address/Sub PDFandNumPages() Dim Folder As Object Dim file As Object Dim fso As Object Dim iExtLen As Integer, iRow As Integer Dim sFolder As String, sExt As String Dim sPDFName As String sExt = "pdf" iExtLen = Len(sExt) iRow = 1 ' Must have a '\' at the end of path sFolder = "C:\your_path_here\" Set fso = CreateObject("Scripting.FileSystemObject") If sFolder <> "" Then Set Folder = fso.GetFolder(sFolder) For Each file In Folder.Files If Right(file, iExtLen) = sExt Then Cells(iRow, 1).Value = file.Name Cells(iRow, 2).Value = pageCount(sFolder & file.Name) iRow = iRow + 1 End If Next file End If End Sub Function pageCount(sFilePathName As String) As Integer Dim nFileNum As Integer Dim sInput As String Dim sNumPages As String Dim iPosN1 As Integer, iPosN2 As Integer Dim iPosCount1 As Integer, iPosCount2 As Integer Dim iEndsearch As Integer ' Get an available file number from the system nFileNum = FreeFile 'OPEN the PDF file in Binary mode Open sFilePathName For Binary Lock Read Write As #nFileNum ' Get the data from the file Do Until EOF(nFileNum) Input #1, sInput sInput = UCase(sInput) iPosN1 = InStr(1, sInput, "/N ") + 3 iPosN2 = InStr(iPosN1, sInput, "/") iPosCount1 = InStr(1, sInput, "/COUNT ") + 7 iPosCount2 = InStr(iPosCount1, sInput, "/") If iPosN1 > 3 Then sNumPages = Mid(sInput, iPosN1, iPosN2 - iPosN1) Exit Do ElseIf iPosCount1 > 7 Then sNumPages = Mid(sInput, iPosCount1, iPosCount2 - iPosCount1) Exit Do ' Prevent overflow and assigns 0 to number of pages if strings are not in binary ElseIf iEndsearch > 1001 Then sNumPages = "0" Exit Do End If iEndsearch = iEndsearch + 1 Loop ' Close pdf file Close #nFileNum pageCount = CInt(sNumPages) End Function 部分)。